I have implemented a JMS Invoker that can be used for Spring remote
invocations. As I prepared to submit it to the Spring developers for
consideration to have it integrated with the framework, I notice that
there is already an implementation in the sandbox! I guess I should
have looked there first before writing my own.
Anyway, I am submitting my implementation as is
(http://opensource.atlassian.com/projects/spring/browse/SPR-1231) in
the hope that we can compare the two implementations to see if perhaps
we can take the best ideas from both in order to include this in the
core distribution someday. (Or perhaps just discard mine altogether
if it is vastly inferior :)
The high level difference between the two is that my implementation
tends to do things more manually (such as using JmsTemplate and
Destination directly) whereas the sandbox implementation uses
QueueRequestor. Both implementations use the great remoting
abstraction that is provided by Spring.
One major difference between the two is the type of Message that is
sent. At first I tried to use ObjectMessage like the sandbox
implementation. However, when I tried to invoke a method that uses
long as a parameter, I get:
org.springframework.jms.MessageFormatException: Deserialization
failed: No ClassLoaders found for: long; nested exception is
javax.jms.MessageFormat
Exception: Deserialization failed: No ClassLoaders found for: long;
nested exception is javax.jms.MessageFormatException: Deserialization
failed: No ClassLoaders found for: long
javax.jms.MessageFormatException: Deserialization failed: No
ClassLoaders found for: long
at com.tibco.tibjms.TibjmsObjectMessage.getObject(TibjmsObjectMessage.ja=
va:199)
at ets.common.jmsinvoker.JmsInvokerServiceExporter$1.doInJms(JmsInvokerS=
erviceExporter.java:72)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:582=
)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:594=
)
=20
So it looks like Tibco has issues with serialization and primitives.=20
Therefore, I decided to use BytesMessage and serialize the objects to
a byte array myself. If we decide to go this route, perhaps we can
provide hooks for end users to perform custom serialization (to
provide compression and encryption for instance).
Another feature that I added is the ability to process a message
before it is sent by the client invoker and again before it is
processed by the server invoker. This provides the ability to add JMS
header data to pass authentication information (which can then be
populated in an Acegi thread local) and any other metadata required.
I noticed that the sandbox implementation uses temporary queues to
reply to clients. Does this have any effect on performance? In my
implementation, request and response queues are required, but I am
open to using temporary queues if the performance hit is negligible.
In the interest of full disclosure, I am a total noob at JMS so please
let me know if I'm doing anything crazy. Based on your feedback, I
would be happy to merge the changes with the sandbox implementation
(if any are suggested) and submit a patch.
Thanks for your help (and for a great framework)!
Patrick
|