Question about Remoting, Marshalling, and EJBs
ron_sigal Mar 8, 2008 6:27 PMI'm looking at an old Remoting issue, JBREM-167 "RMI Invoker does not use true remoting marshalling/unmarshalling" and I have a question. This issue concerns the Remoting RMI transport, which, as an alternative to the more commonly used "socket" transport, makes invocations using Java RMI. If the "jboss.remoting:service=Connector,transport=socket" Connector in conf/jboss-service.xml were configured to use the RMI tranport, then EJB2 calls would be transported by Java RMI.
Currently, the RMI transport uses org.jboss.invocation.unified.marshall.InvocationMarshaller to marshal invocations on the client side and org.jboss.invocation.unified.marshall.InvocationUnMarshaller to unmarshal invocations on the server side. Their main function, other than serializing and deserializing the invocation, is to add and remove transaction context information:
// From InvocationMarshaller:
public Object addDecoration(Object dataObject) throws IOException {
if(dataObject instanceof InvocationRequest)
{
InvocationRequest remoteInv = (InvocationRequest) dataObject;
if(remoteInv.getParameter() instanceof Invocation)
{
Invocation inv = (Invocation) remoteInv.getParameter();
MarshalledInvocation marshInv = new MarshalledInvocation(inv);
if(inv != null)
{
// now that have invocation object related to ejb invocations,
// need to get the possible known payload objects and make sure
// they get serialized.
try
{
marshInv.setTransactionPropagationContext(getTransactionPropagationContext());
}
catch(SystemException e)
{
log.error("Error setting transaction propagation context.", e);
throw new IOException("Error setting transaction context. Message: " + e.getMessage());
}
// reset the invocation parameter within remote invocation
remoteInv.setParameter(marshInv);
}
else
{
//Should never get here, but will check anyways
log.error("Attempting to marshall Invocation but is null. Can not proceed.");
throw new IOException("Can not process data object due to the InvocationRequest's parameter being null.");
}
}
}
return dataObject;
}
and
// From InvocationUnMarshaller:
public Object removeDecoration(Object obj) throws IOException
{
if(obj instanceof InvocationRequest)
{
InvocationRequest remoteInv = (InvocationRequest) obj;
Object param = remoteInv.getParameter();
if(param instanceof MarshalledInvocation)
{
MarshalledInvocation mi = (MarshalledInvocation) param;
Object txCxt = mi.getTransactionPropagationContext();
if(txCxt != null)
{
TransactionPropagationContextImporter tpcImporter = TransactionPropagationContextUtil.getTPCImporter();
mi.setTransaction(tpcImporter.importTransactionPropagationContext(txCxt));
}
}
}
return obj;
}
On the other hand, when the server returns a response, no marshalling is performed on the server side and no unmarshalling is performed on the client side: the response is passed directly to the RMI runtime. The point of JBREM-167 is to change the RMI server invoker to use a configured marshaller and to change the RMI client invoker to use a configured unmarshaller. This way, someone could interpose, for example, encrypting or compressing marshaller/unmarshallers, which is not currently possible.
My questions:
1. Does anyone care about having this feature?
2. This change would mean that the InvocationMarshaller would be used on the server side when returning a response and InvocationUnMarshaller would be used on the client side to unmarshal the response. Would adding and removing transaction context in the server-to-client direction have any implications?
3. Since EJB3 handles transaction information in an interceptor and doesn't, by default, configure any marshaller or unmarshaller, am I right that this issue is irrelevant to EJB3?
Thanks,
Ron