]
Ron Sigal commented on JBREM-990:
---------------------------------
Applied changes for JBREM-960 to 2.x branch.
CLONE [JBREM-960] - Remoting configured with Servlet invoker can
return misleading Exceptions when Servlet path is incorrect
----------------------------------------------------------------------------------------------------------------------------
Key: JBREM-990
URL:
https://jira.jboss.org/jira/browse/JBREM-990
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
Assignee: Ron Sigal
Fix For: 2.4.0.SP1
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: