These converters solved my problem. However, I had to override
resolveClass() in my ObjectInputStream, and explicitly use the
definition class-loader of my class; it appears that the type conversion
detection uses the context class-loader of Camel, which (when Camel is
in jetty/lib/ext) does not "see" the class definitions of deployed web
applications. So, for future reference, this scenario needs something like:
ObjectInputStream ois = new ObjectInputStream(baos) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
ClassLoader dcl = MyClass.class.getClassLoader();
try {
Class<?> c = dcl.loadClass(desc.getName());
return c;
} catch (ClassNotFoundException e) {
// silence; will delegate to parent implementation
}
return super.resolveClass(desc);
}
};
Thanks again for your help.
On 26/2/2010 3:34 πμ, Stephen Gargan wrote:
Alexandros,
As Claus mentions, once you get classloaders separating your contexts
you really need to experiment to get vm routes working. The class
'MyClass' is loaded by each war's classloader and though they are
essentially the same they are treated like entirely different classes.
One way to get around this is to make MyClass serializable and
serialize instances it before dispatching them to the vm endpoint. On
the other side, in your other war, you can unserialize it. Its easy to
write a Camel converter to do this e.g.
@Converter
public class MyClassConverter
{
@Converter
public MyClass fromByteArray(byte[] serialized) throws Exception
{
MyClass dto = null;
if(serialized instanceof byte[])
{
ByteArrayInputStream baos = new ByteArrayInputStream(serialized);
ObjectInputStream ois = new ObjectInputStream(baos);
dto = (MyClass)ois.readObject();
}
return dto;
}
@Converter
public byte[] toByteArray(Serializable dto) throws IOException
{
byte[] serialized = null;
if(dto instanceof Serializable)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(dto);
oos.close();
serialized = baos.toByteArray();
}
return serialized;
}
}
You'll need to add the following file to your war
META-INF/services/org/apache/camel/TypeConverter and in it add the
package containing the Converter. Then you'll be able to build routes
like in the test below
class VMTest extends CamelTestSupport
{
@Override
protected RouteBuilder createRouteBuilder() throws Exception
{
return new RouteBuilder()
{
@Override
public void configure() throws Exception
{
// send in one war
from("direct:in").convertBodyTo(byte[].class).to("vm:mychannel");
// receive in another
from("vm:mychannel").convertBodyTo(MyClass.class).to("mock:serialized");
}
};
}
@Test
public void testVmRoutesWithDTO() throws Exception
{
MockEndpoint mock = getMockEndpoint("mock:serialized");
mock.expectedMessageCount(1);
sendBodies("direct:in", new MyClass());
mock.await();
mock.assertIsSatisfied();
}
}
Give this a try I think it should solve your problem.
regards,
ste
On Thu, Feb 25, 2010 at 2:54 PM, Alexandros Karypidis<[email protected]> wrote:
Thank you for your replies. I have managed to get the VM transport to work
by putting Camel (and its dependencies) in jetty/lib/ext. However, I am only
able to exchange primitive Java types. Camel complains about not having a
type converter for it. I am using POJOs like this:
The inteface (exists in both WARs):
@InOnly // vm:/ transport is one-way
public interface Messaging {
send (Integer i); // works
send (String s); // works
send (MyClass val); // FAILS !<=======
}
In one WAR I have:
@Consume(uri = "vm:mychannel")
public void onMessage(String msg) {...} // works
@Consume(uri = "vm:mychannel")
public void onMessage(Integer msg) {...} // works
@Consume(uri = "vm:mychannel")
public void onMessage(MyClass msg) {...} // NOT INVOKED !<=======
In the other WAR I have:
@Produce(uri = "vm:mychannel")
protected Messaging engine;
public void testMessaging() {
send ("hello"); // works
send (1); // works
send(new MyClass()); // FAILS!<=====
}
MyClass is in both WARs.
On 24/2/2010 2:56 μμ, Ashwin Karpe wrote:
Hi,
Check out the SEDA, Direct and VM components for in-VM communication
http://camel.apache.org/seda.html http://camel.apache.org/seda.html
http://camel.apache.org/direct.html http://camel.apache.org/direct.html
http://camel.apache.org/direct.html http://camel.apache.org/direct.html
For differences between them, check
http://camel.apache.org/how-do-the-direct-event-seda-and-vm-endpoints-compare.html
http://camel.apache.org/how-do-the-direct-event-seda-and-vm-endpoints-compare.html
Cheers,
Ashwin...
karypid wrote:
Hello,
I need to create a modular application using Camel. The structure is
that there is a "core" module and some peripheral "adapter" modules,
each of which is packaged as a WAR and deployed in the same container
(Jetty).
What would be the most efficient way perform synchronous request-reply
message exchanges among the "core" and the "adapters"?
The aparent way for me is to have each module export its API via a web
service and have one module invoke the other using SOAP/HTTP.
Performance is important however and I'd like to avoid that, since all
these WARs are meant to be installed in the same JVM (one jetty
container).
Thank you in advance.
-----
---
Ashwin Karpe, Principal Consultant, PS - Opensource Center of Competence
Progress Software Corporation
14 Oak Park Drive
Bedford, MA 01730
---
+1-972-304-9084 (Office)
+1-972-971-1700 (Mobile)
----
Blog: http://opensourceknowledge.blogspot.com/