[jboss-remoting-issues] [JBoss JIRA] Commented: (JBREM-960) Remoting configured with Servlet invoker can return misleading Exceptions when Servlet path is incorrect

Ron Sigal (JIRA) jira-events at lists.jboss.org
Mon Jun 16 18:09:33 EDT 2008


    [ http://jira.jboss.com/jira/browse/JBREM-960?page=comments#action_12417484 ] 
            
Ron Sigal commented on JBREM-960:
---------------------------------

I wasn't able to reproduce the exception given above, but by messing up the Naming configuration I was able to get:

 Exception in thread "main" javax.naming.ServiceUnavailableException: Unexpected failure [Root exception is org.jboss.remoting.CannotConnectException: Can not connect http client invoker. invalid stream header. Response: Internal Server Error/500.]
     at org.jboss.naming.interceptors.ExceptionInterceptor.invoke(ExceptionInterceptor.java:71)
     at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:70)
     at org.jboss.proxy.ClientMethodInterceptor.invoke(ClientMethodInterceptor.java:74)
     at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:100)
     at $Proxy0.lookup(Unknown Source)
     at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:667)
     at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:627)
     at javax.naming.InitialContext.lookup(InitialContext.java:351)
     at org.jboss.tutorial.http_https.client.Client.calculate(Client.java:56)
     at org.jboss.tutorial.http_https.client.Client.main(Client.java:41)
 Caused by: org.jboss.remoting.CannotConnectException: Can not connect http client invoker. invalid stream header. Response: Internal Server Error/500.
     at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:350)
     at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:139)
     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.naming.interceptors.ExceptionInterceptor.invoke(ExceptionInterceptor.java:57)
     ... 9 more
 Caused by: java.io.StreamCorruptedException: invalid stream header
     at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:753)
     at java.io.ObjectInputStream.<init>(ObjectInputStream.java:268)
     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:518)
     at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:309)
     ... 17 more

I made two changes in HTTPClientInvoker:

1. When HTTPClientInvoker.readResponse() experiences an exception, it tests for an end of file condition:

      catch (IOException e)
      {
         if (-1 == is.read())
         {
            throw new EOFException();
         }
         throw e;
      }

    and, in the event of an end of file, throws EOFException, which is somewhat better than java.io.StreamCorruptedException: invalid stream header.

2. When HTTPClientInvoker.useHttpURLConnection() catches an exception, it tries to add a response message and response code to the message in the CannotConnectException it throws:

      catch (Exception e)
      {
         String message = "Can not connect http client invoker.";
         if (e.getMessage() != null)
            message += " " + e.getMessage() + ".";
 
         try
         {
            String responseMessage = conn.getResponseMessage();
            int code = conn.getResponseCode();
            message += " Response: " + responseMessage + "/" + code + ".";
         }
         catch (IOException e1)
         {
            log.debug("Unable to retrieve response message", e1);
         }
         throw new CannotConnectException(message, e);
      }

With those changes, the stracktrace becomes

 Exception in thread "main" javax.naming.ServiceUnavailableException: Unexpected failure [Root exception is org.jboss.remoting.CannotConnectException: Can not connect http client invoker. Response: Internal Server Error/500.]
     at org.jboss.naming.interceptors.ExceptionInterceptor.invoke(ExceptionInterceptor.java:71)
     at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:70)
     at org.jboss.proxy.ClientMethodInterceptor.invoke(ClientMethodInterceptor.java:74)
     at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:100)
     at $Proxy0.lookup(Unknown Source)
     at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:667)
     at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:627)
     at javax.naming.InitialContext.lookup(InitialContext.java:351)
     at org.jboss.tutorial.http_https.client.Client.calculate(Client.java:56)
     at org.jboss.tutorial.http_https.client.Client.main(Client.java:41)
 Caused by: org.jboss.remoting.CannotConnectException: Can not connect http client invoker. Response: Internal Server Error/500.
     at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:350)
     at org.jboss.remoting.transport.http.HTTPClientInvoker.transport(HTTPClientInvoker.java:139)
     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.naming.interceptors.ExceptionInterceptor.invoke(ExceptionInterceptor.java:57)
     ... 9 more
 Caused by: java.io.EOFException
     at org.jboss.remoting.transport.http.HTTPClientInvoker.readResponse(HTTPClientInvoker.java:530)
     at org.jboss.remoting.transport.http.HTTPClientInvoker.useHttpURLConnection(HTTPClientInvoker.java:309)
     ... 17 more

[Actually, it looks like I had already added the response message/code when I got the first stack trace].

I think this looks a lot better.  I'm sure it would be possible to do something more sophisticated by looking at response codes, but then I'd probably have to worry about different behaviors from different servers.

Galdor, does this look OK to you?  Do you want to try it with your original exception?

> Remoting configured with Servlet invoker can return misleading Exceptions when Servlet path is incorrect
> --------------------------------------------------------------------------------------------------------
>
>                 Key: JBREM-960
>                 URL: http://jira.jboss.com/jira/browse/JBREM-960
>             Project: JBoss Remoting
>          Issue Type: Bug
>      Security Level: Public(Everyone can see) 
>          Components: transport
>    Affects Versions: 2.4.0.GA (Pinto), 2.2.2.SP8, 2.4.1.Beta
>            Reporter: Galder Zamarreno
>         Assigned To: Ron Sigal
>             Fix For: 2.2.2.SP8
>
>
> 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?

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the jboss-remoting-issues mailing list