`any' de/marshalling between ORBit and JavaORB



Hi,

We've found a really strange interoperability bug between ORBit 0.5.3 and
JavaORB 2.2.6.

Consider this IDL:

module HasAny {
	interface Notifier {
		enum		MessageType { MT_MessageContentThing };

		struct Envelope {
			MessageType	mtype;
			boolean		unread;
		};

		struct Message {
			// The order of these fields doesn't matter
			Envelope	e;
			any		content;
		};
		typedef sequence<Message> Messages;

		struct MessageContentThing {
			long		mid;
		};

		Messages getAll();
	};
};


The implementation for getAll() returns two Message structures. My Perl
(CORBA::ORBit 0.4.2) client can properly retrieve both structures, with
MessageContentThings in the `content' members, from the Perl servant.

An equivalent Java servant and client can also communicate without any
problems.

But the Java client can't properly demarshal getAll()'s return value from
the Perl servant. After correctly demarshalling the first message
structure, the second message's Envelope structure members are corrupted
(which results in a BAD_OPERATION exception, because the enum doesn't have
a valid value).

The same thing seems to happen when the Perl client calls getAll() on the
Java servant.

The Java client can talk to the Perl servant if I move "boolean unread" in
struct Envelope so it's not the last member.


I've attached my test case. To duplicate:

* set your classpath to something like
CLASSPATH=$CLASSPATH:corba_pkg:/usr/local/JavaORBv2_2_6/lib/JavaORBv2_2_6.jar

* set your path to something like
	PATH=$PATH:/usr/local/JavaORBv2_2_6/bin:/usr/local/jdk/bin

* run `make' to generate and compile all the Java stuff

* run `./perlserveur.pl | ./perlcliente.pl' - this works

* run `java HasAny/JavaServeur | java grrr' - this works

* run `./perlserveur.pl | java grrr' - this fails:
Exception in thread "main" org.omg.CORBA.BAD_OPERATION:   minor code: 0
completed: No
	at
HasAny.NotifierPackage.MessageType.from_int(MessageType.java:46)
	at
HasAny.NotifierPackage.MessageTypeHelper.read(MessageTypeHelper.java:81)
	at
HasAny.NotifierPackage.EnvelopeHelper.read(EnvelopeHelper.java:89)
	at
HasAny.NotifierPackage.MessageHelper.read(MessageHelper.java:89)
	at
HasAny.NotifierPackage.MessagesHelper.read(MessagesHelper.java:85)
	at HasAny._NotifierStub.getAll(_NotifierStub.java:37)
	at grrr.main(grrr.java:19)

* run `java HasAny/JavaServeur' on one terminal, and paste the IOR to
`./perlcliente.pl' on another - this fails:
Error demarshalling result at ./perlcliente.pl line 11, <> chunk 1.
Exception: CORBA::MARSHAL ('IDL:omg.org/CORBA/MARSHAL:1.0')
    (0, COMPLETED_YES)
   Error marshalling parameter or result


I can't tell at this point whether the problem is with ORBit or JavaORB,
or perhaps me. Any assistance would be greatly appreciated.
module HasAny {
	interface Notifier {
		enum		MessageType { MT_MessageContentThing };

		struct Envelope {
			// If this is a long instead of an enum, JavaORB
			// gets the typecode kind value as tk_null but
			// doesn't throw an exception (because it doesn't
			// check the value for validity...)
			MessageType	mtype;
			// 'unread' must be the last field in the structure
			// to cause an exception
			boolean		unread;
		};

		struct Message {
			// The order of these fields doesn't matter
			Envelope	e;
			any		content;
		};
		typedef sequence<Message> Messages;

		struct MessageContentThing {
			long		mid;
		};

		Messages getAll();
	};
};
#!/usr/bin/perl -w

BEGIN { push @ARGV, '-ORBIIOPIPv4=1', '-ORBIIOPUSock=0'; }

use strict;
use CORBA::ORBit idl => [ qw(HasAny.idl) ];
use Error qw(:try);

package HasAny::NotifierImpl;
use strict;
use vars qw(@ISA);

@ISA = qw(POA_HasAny::Notifier);

sub new ($) {
	my ($class, $poa) = @_;

	return bless {}, $class;
}

sub getAll ($) {
	my $self = shift;

	my $env1 = {
		id	=> 1,
		at	=> 2,
		mtype	=> 'MT_MessageContentThing',
		recip	=> 3,
		unread	=> 1,
	};

	my $newm = { mid => 666 };
	my $msg = {
		e => $env1,
		content => new CORBA::Any(new CORBA::TypeCode('IDL:HasAny/Notifier/MessageContentThing:1.0'), $newm),
	};

	return [ $msg, $msg ];
}


package main;

my $orb = CORBA::ORB_init('')
	or die "CORBA::ORB_init() failed: $!. Stopped";
my $poa = $orb->resolve_initial_references('RootPOA')
	or die "resolve fail0red: $!. Stopped";

my $servant = new HasAny::NotifierImpl;
my $id = $poa->activate_object($servant);
my $ref = $poa->id_to_reference($id);
$| = 1;
print $orb->object_to_string($ref), "\n";

$poa->_get_the_POAManager->activate;

$orb->run;
#!/usr/bin/perl -w

use strict;
use CORBA::ORBit idl => [ qw(HasAny.idl) ];
use Error qw(:try);

my $orb = CORBA::ORB_init('');
chomp(my $ior = <>);
my $x = $orb->string_to_object($ior);

my ($m1, $m2) = @{$x->getAll};

foreach my $m ($m1, $m2) {
	print "Got a $m\n";
	print "\tunread $m->{e}->{unread}\n";
	print "\tcontent mid: ", $m->{content}->value->{mid}, "\n";
	print "\n";
}
# Be sure to source env.sh before calling make.

IDL2JAVA = java JavaORB.compiler.IdlCompiler -nopackage -poa -I. -all
IDL = HasAny.idl
COMPILED_IDL = corba_pkg/HasAny
JAVAC = javac

all: grrr.class HasAny/JavaServeur.class

grrr.class: grrr.java $(COMPILED_IDL)
	$(JAVAC) grrr.java

HasAny/NotifierPOAImpl.class: NotifierPOAImpl.java $(COMPILED_IDL)
	$(JAVAC) NotifierPOAImpl.java
	mkdir HasAny 2>/dev/null
	mv NotifierPOAImpl.class HasAny

HasAny/JavaServeur.class: JavaServeur.java HasAny/NotifierPOAImpl.class $(COMPILED_IDL)
	$(JAVAC) JavaServeur.java
	mv JavaServeur.class HasAny

$(COMPILED_IDL): $(IDL)
	rm -rf $(COMPILED_IDL)
	$(IDL2JAVA) $(IDL)
	javac `find $(COMPILED_IDL) -name '*.java' -type f`

clean:
	rm -rf $(COMPILED_IDL) HasAny
	rm -f grrr.class
import java.io.*;
import HasAny.*;
import HasAny.NotifierPackage.*;
import org.omg.CORBA.*;

public class grrr {
	public static void main(String[] args) throws org.omg.CORBA.TypeCodePackage.BadKind
	{
		ORB orb = ORB.init();
		org.omg.CORBA.Object obj;
		Notifier x;

		InputStreamReader isr = new InputStreamReader(System.in);
		BufferedReader br = new BufferedReader(isr);
		try {
			String line = br.readLine();
			obj = orb.string_to_object(line);
			Notifier n = NotifierHelper.narrow(obj);
			Message[] heya = n.getAll();
			System.out.println("heya len " + heya.length);
			if (heya.length > 0) {
				Any p = heya[1].content;
				TypeCode type = p.type();
				TCKind kind = type.kind();
				System.out.println("Type is " + type);
				System.out.println("Kind is " + kind);
				System.out.println("Kind value is " + kind.value());
				System.out.println("ID is " + type.id());
			}
		} catch (java.io.IOException e) {
			System.out.println("blarf!!!");
		}
	}
};
package HasAny;

public class JavaServeur
{
	public static void main(String args[]) throws
		org.omg.PortableServer.POAPackage.ServantAlreadyActive,
		org.omg.PortableServer.POAPackage.WrongPolicy,
		org.omg.PortableServer.POAPackage.ObjectNotActive,
		org.omg.PortableServer.POAManagerPackage.AdapterInactive
	{
		org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null);

		org.omg.CORBA.Object objPoa = null;
		org.omg.PortableServer.POA rootPOA = null;
		try {
			objPoa = orb.resolve_initial_references("RootPOA");
		}
		catch (org.omg.CORBA.ORBPackage.InvalidName e) {}

		rootPOA = org.omg.PortableServer.POAHelper.narrow(objPoa);

		NotifierPOAImpl ni = new NotifierPOAImpl(orb);
		byte[] servantId = rootPOA.activate_object(ni);
		org.omg.CORBA.Object obj
				= rootPOA.id_to_reference(servantId);
		String reference = orb.object_to_string(obj);
		System.out.println(reference);
		System.out.flush();

		rootPOA.the_POAManager().activate();
		orb.run();
	}
}
package HasAny;

import org.omg.CORBA.*;
import HasAny.NotifierPackage.*;

public class NotifierPOAImpl extends NotifierPOA
{
	ORB orb;

	public NotifierPOAImpl(ORB orb)
	{
		super();
		this.orb = orb;
	}

	public Message[] getAll()
	{
		Envelope e = new Envelope();
		e.mtype = MessageType.MT_MessageContentThing;
		e.unread = true;

		MessageContentThing nmtm = new MessageContentThing(666);

		Any content = this.orb.create_any();
		MessageContentThingHelper.insert(content, nmtm);

		Message m1 = new Message(e, content);
		Message m2 = new Message(e, content);
		Message[] ms = { m1, m2 };
		return ms;
	}
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]