Archived

This forum has been archived. Please start a new discussion on GitHub.

NoObjectFactoryException for method-less class

Hi,

I'm using Ice 3.1.0.
I'm seeing an Ice::NoObjectFactoryException for a class with no methods.
My understanding from the documentation is that an object factory is only required to instantiate classes which has methods. Indeed, I have a number of other classes defined in slice, with no methods, which I can happily send around without object factories.

I can't work out what's different about this particular class that makes it break, I wonder if anyone has any ideas?

My interface is pretty simple:

interface Localise2dConsumer
{
void setData( Localise2dData obj );
};

where Localise2dData is a method-less class.

When 'setData' is called, I see the following from the binary (called orcamon) which implements Localise2dConsumer:

orcamon: warning: dispatch exception: /home/users/a.brooks/orca2/src/interfaces/cpp/orca/localise2d.cpp:1260: Ice::NoObjectFactoryException:
protocol error: no suitable object factory found for `::orca::Localise2dData'
identity: 544D1B5B-2A5F-4C28-84B7-347E3E6B3D43
facet:
operation: setData



Any suggestions for what to look for?

Thanks,

Alex

Comments

  • benoit
    benoit Rennes, France
    Hi Alex,

    Which OS / compiler do you use? Is your server linking with the object file containing the definition of the Localise2dData class?

    Cheers,
    Benoit.
  • benoit wrote:
    Which OS / compiler do you use? Is your server linking with the object file containing the definition of the Localise2dData class?

    Yes, both sides are definitely linking against the definition of the Localise2dData class. I'm using gcc-4.0 on Debian Linux.

    I can be sure that I'm linking against the definition of Localise2d because I put a trace statement in my setData() implementation and I can actually print out the Localise2d class correctly. Why this is so, I don't understand -- I'd have thought the exception would cause the stack to unwind before the body of setData is executed.

    Maybe it would help if I also included the relevant class definitions:

    struct Time {
    int seconds;
    int useconds;
    };

    class OrcaObject {
    Time timeStamp;
    };

    struct Pose2dHypothesis {
    Frame2d mean;
    Covariance2d cov;
    float weight;
    };

    sequence<Pose2dHypothesis> Pose2dHypotheses;

    class Localise2dData extends OrcaObject {
    Pose2dHypotheses hypotheses;
    };

    where Frame2d and Covariance2d are simple structs.
  • matthew
    matthew NL, Canada
    When exactly is this exception thrown then? If not during the unmarshaling then it must appear at a later point? Did you trace through to see where it actually occurs?
  • matthew wrote:
    When exactly is this exception thrown then? If not during the unmarshaling then it must appear at a later point? Did you trace through to see where it actually occurs?

    It seems to be getting called from within the slice-generated code in localise2d.cpp:

    void
    orca::__patch__Localise2dDataPtr(void* __addr, ::Ice::ObjectPtr& v)
    {
    ::orca::Localise2dDataPtr* p = static_cast< ::orca::Localise2dDataPtr*>(__addr);
    assert(p);
    *p = ::orca::Localise2dDataPtr::dynamicCast(v);
    if(v && !*p)
    {
    ::Ice::NoObjectFactoryException e(__FILE__, __LINE__);
    e.type = ::orca::Localise2dData::ice_staticId();
    throw e;
    }
    }

    I'm assuming (but this is just a guess, I'm not sure how to check it) that the un-marshalling code catches this exception, issues the warning I mentioned in the previous post, and continues.
  • benoit
    benoit Rennes, France
    Hi,

    I don't believe setData is being executed when this warning is printed. The exception is thrown when unmarshalling the data from the wire before calling the implementation of setData. I suspect that your client retries the setData invocation and the second invocation succeeds for some reasons. Could you confirm this by enabling tracing on your client with the Ice.Trace.Protocol and Ice.Trace.Retry=1 properties?

    In any case, I don't understand why you're getting this exception :(. I tried to reproduce it with your definitions (alhough the definition for Frame2d and Covariance2d were missing) and it worked.

    Could you try to include the localise2d.h header in the compilation unit where setData is defined? This shouldn't make a difference on Linux but I know that's required on some platforms to get the static objects initialized.

    One other thing which you could try and could give us some hints is to modify the generated code that you posted, change the following line:

    e.type = :rca::Localise2dData::ice_staticId();

    to

    e.type = v->ice_id();

    The warning should tell us what is the type of the object received from the wire with this change.

    Of course, the best way to expediate this matter would be to send us a small test case. Is that possible?

    Cheers,
    Benoit.
  • Hi Benoit,

    Found it! This was the bit that gave me the hint:
    benoit wrote:
    One other thing which you could try and could give us some hints is to modify the generated code that you posted, change the following line:

    e.type = :rca::Localise2dData::ice_staticId();

    to

    e.type = v->ice_id();

    The warning should tell us what is the type of the object received from the wire with this change.

    My setup is a little complicated... setData() actually gets called via IceStorm. A sender program publishes data of two different types (Localise2dData and Particle2dData), to two different IceStorm topics. A receiver registers for only one of these topics. My mistake was that, through a cut-and-paste error, the two topics had the same name. So the receiver was actually getting data for _both_ topics. setData() was therefore being called once with Particle2dData (which caused the exception), then once with Localise2dData (which worked). Since the data is always produced in pairs, I thought it was the same call.


    Thanks very much for the help!

    Alex
  • benoit
    benoit Rennes, France
    Great, I'm glad you found the problem :).

    Cheers,
    Benoit.