Uploaded image for project: 'JBoss Remoting'
  1. JBoss Remoting
  2. JBREM-990

CLONE [JBREM-960] - Remoting configured with Servlet invoker can return misleading Exceptions when Servlet path is incorrect

    Details

    • Estimated Difficulty:
      Low

      Description

      I've been struggling to set up a ServletInvoker in Remoting to be able to
      use the unified invoker to talk to EJB2 beans in AS/EAP 4.x. I had the Connector
      set up like this:

      <mbean code="org.jboss.remoting.transport.Connector"
      name="jboss.remoting:service=connector,transport=servlet"
      display-name="Servlet transport Connector">
      <attribute name="Configuration">
      <config>
      <invoker transport="servlet">
      <attribute name="dataType" isParam="true">invocation</attribute>
      <attribute name="marshaller" isParam="true">org.jboss.invocation.unified.marshall.InvocationMarshaller</attribute>
      <attribute name="unmarshaller" isParam="true">org.jboss.invocation.unified.marshall.InvocationUnMarshaller</attribute>
      <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
      <attribute name="serverBindPort">8080</attribute>
      <attribute name="path">unified-http-invoker/ServerInvokerServlet</attribute>
      </invoker>
      <handlers>
      <handler subsystem="invoker">jboss:service=invoker,type=unified-http</handler>
      </handlers>
      </config>
      </attribute>
      </mbean>

      But the path attribute was incorrect. Remoting was coming back with something like this:

      org.jboss.remoting.CannotConnectException: Can not connect http client invoker.
      at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:333)
      at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:135)
      at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:122)
      at org.jboss.remoting.Client.invoke(Client.java:1634)
      at org.jboss.remoting.Client.invoke(Client.java:548)
      at org.jboss.invocation.unified.interfaces.UnifiedInvokerProxy.invoke(UnifiedInvokerProxy.java:183)
      at org.jboss.invocation.InvokerInterceptor.invokeInvoker(InvokerInterceptor.java:365)
      at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:197)
      at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:61)
      at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:70)
      at org.jboss.proxy.ejb.HomeInterceptor.invoke(HomeInterceptor.java:184)
      at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:100)
      at $Proxy0.create(Unknown Source)
      at com.acme.ejb2.slsb.TimerEnquirerHttpTest.test000(TimerEnquirerHttpTest.java:34)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at junit.framework.TestCase.runTest(TestCase.java:164)
      at junit.framework.TestCase.runBare(TestCase.java:130)
      at junit.framework.TestResult$1.protect(TestResult.java:106)
      at junit.framework.TestResult.runProtected(TestResult.java:124)
      at junit.framework.TestResult.run(TestResult.java:109)
      at junit.framework.TestCase.run(TestCase.java:120)
      at junit.framework.TestSuite.runTest(TestSuite.java:230)
      at junit.framework.TestSuite.run(TestSuite.java:225)
      at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
      at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
      Caused by: java.io.StreamCorruptedException: invalid stream header
      at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:764)
      at java.io.ObjectInputStream.<init>(ObjectInputStream.java:277)
      at org.jboss.remoting.loading.ObjectInputStreamWithClassLoader.<init>(ObjectInputStreamWithClassLoader.java:95)
      at org.jboss.remoting.serialization.impl.java.JavaSerializationManager.createInput(JavaSerializationManager.java:54)
      at org.jboss.remoting.marshal.serializable.SerializableUnMarshaller.getMarshallingStream(SerializableUnMarshaller.java:72)
      at org.jboss.remoting.marshal.serializable.SerializableUnMarshaller.read(SerializableUnMarshaller.java:119)
      at org.jboss.invocation.unified.marshall.InvocationUnMarshaller.read(InvocationUnMarshaller.java:59)
      at org.jboss.remoting.transport.http.HTTPClientInvoker.readResponse(HTTPClientInvoker.java:471)
      at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:305)
      ... 31 more

      Now, to get this Exception is very misleading. It generally means that either you have different
      client and server side Remoting versions, or you're using different serialization methods on either
      side.

      Once I started to dig into what Remoting was doing, I spotted HTTPClientInvoker does the following in
      useHttpURLConnection() method:

      if (sendingData)
      {
      //POST or PUT
      conn.setDoOutput(true);
      conn.setDoInput(true);
      conn.setRequestMethod(type);

      OutputStream stream = conn.getOutputStream();
      if (marshaller instanceof VersionedMarshaller)
      ((VersionedMarshaller) marshaller).write(invocation, stream, Version.getDefaultVersion());
      else
      marshaller.write(invocation, stream);
      responseCode = conn.getResponseCode();
      InputStream is = (responseCode < 400) ? conn.getInputStream() : conn.getErrorStream();
      Map headers = conn.getHeaderFields();
      if (metadata == null)

      { metadata = new HashMap(); }

      // sometimes I get headers with "null" keys (I don't know who's fault is it), so I need
      // to clean the header map, unless I want to get an NPE thrown by metadata.putAll()
      if (headers != null)
      {
      for(Iterator i = headers.entrySet().iterator(); i.hasNext(); )
      {
      Map.Entry e = (Map.Entry)i.next();
      if (e.getKey() != null)

      { metadata.put(e.getKey(), e.getValue()); }

      }
      }

      metadata.put(HTTPMetadataConstants.RESPONSE_CODE_MESSAGE, conn.getResponseMessage());
      metadata.put(HTTPMetadataConstants.RESPONSE_CODE, new Integer(responseCode));

      result = readResponse(metadata, headers, unmarshaller, is);
      }

      The Exception reported is coming from readResponse() but before that if the Servlet was not available,
      like in my case, conn.getResponseCode() was returning 404.

      Remoting code should check what the response code was, whether this is an invalid code, i.e. does not exist...etc,
      and throw an Exception if invalid, like in this case, giving the caller much better clue of what is going on.

      Thoughts?

        Gliffy Diagrams

          Attachments

            Activity

              People

              • Assignee:
                ron_sigal Ronald Sigal
                Reporter:
                galder.zamarreno Galder ZamarreƱo
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: