0

BusException when trying to use BusMethod that passes Object

asked 2015-04-23 12:41:41 -0700

anonymous user

Anonymous

updated 2015-04-23 12:47:27 -0700

I am seeing a very similar issue as described here: https://ask.allseenalliance.org/question/2028/buserstatus-exception-when-sending-complex-data-types/

But in my case, the empty array cannot be the problem.

When I try to pass an object to the server using a BusMethod, I get a ErrorReplyBusException. However, a function that passes a string works fine.

Here are some code snippets:

    @BusInterface (name = "com.carserverinterface")
public interface CarServerInterface {
    public static String SERVICE_NAME = "com.carserverinterface";
    public static short CONTACT_PORT = 25;

    @BusMethod(signature = "r", replySignature = "y")
    Status sendMessage(Message msg) throws BusException;

    @BusMethod(signature="s", replySignature="b")
    boolean sendString(String string) throws BusException;
}

The message signatures are as follows:

public class Message {

@Position(0)
@Signature("i")
public static final int MESSAGE_LOCK_CAR = 0x01;

@Position(1)
@Signature("i")
public static final int MESSAGE_UNLOCK_CAR = 0x02;

/**
 * Message Fields
 */
@Position(2)
@Signature("i")
protected int       mMsgId;


public Message(){

}

public int getMsgId(){
    return mMsgId;
}

}

I found that if I did not provide a signature for the static fields, I would get an Annotation exception.

I call the BusMethod in this way:

            case SEND_MESSAGE_ALLJOYN: {
                addMessageToLog("Sending message...");
                if (mIsConnected){
                    try {
                        addMessageToLog("Sending message to car server..");
                        Status status = mCarInterface.sendMessage((Message) msg.obj);
                        if (status != Status.OK){
                            addMessageToLog("Send message failed");
                        }
                    } catch (BusException e) {
                        addMessageToLog("Bus Exception sending message");
                    } 
                }
                break;
            }

It may be important to note that I msg.obj is an UnlockMessage object that extends Message:

public class UnlockMessage extends Message {

public UnlockMessage(){
    super();        
    mMsgId = MESSAGE_UNLOCK_CAR;
}

}

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2015-04-23 15:54:10 -0700

georgen gravatar image

updated 2015-04-29 15:15:15 -0700

What you are trying to send is an enumerated value through AllJoyn. What you have encoded is a struct with and alljoyn signature (iii).

AllJoyn does not have any underlying way to understand enumerated values. So you have two options. Send an integer for the enumerated value or send a string representing the enumerated value.

I think all values that are going to be read by AllJoyn must be public. so the protected int mMsgId would most likely cause a problem.

here are some suggested changes. For the BusInterface

@BusInterface (name = "com.carserverinterface")
    public interface CarServerInterface {
    public static String SERVICE_NAME = "com.carserverinterface";
    public static short CONTACT_PORT = 25;

    @BusMethod(signature = "i", replySignature = "y")
    Status sendMessage(int msg) throws BusException;

    @BusMethod(signature="s", replySignature="b")
    boolean sendString(String string) throws BusException;
}

What you really want to send is a 0x01 or 0x02 for lock or unlock you don't need a struct with 3 integers.

For you message class public class Message { public static final int MESSAGE_LOCK_CAR = 0x01; public static final int MESSAGE_UNLOCK_CAR = 0x02;

    /**
     * Message Fields
     */
    protected int       mMsgId;


    public Message(){

    }

    public int getMsgId(){
        return mMsgId;
    }
}

This is just your programs internal representation of the message value no need add position annotations the only value sent accross the wire is the mMsgId. You may need to add a setMgsId method

Sending the lock/unlock message

case SEND_MESSAGE_ALLJOYN: {
    addMessageToLog("Sending message...");
    if (mIsConnected){
        try {
            addMessageToLog("Sending message to car server..");
            Status status = mCarInterface.sendMessage(msg.getMsgId());
            if (status != Status.OK){
                addMessageToLog("Send message failed");
            }
        } catch (BusException e) {
            addMessageToLog("Bus Exception sending message");
        } 
    }
    break;
}

Update Edit based on comments

The Message Object originally had a byte[] mPayload field in addition to the mMsgId field but I removed it to make the object simpler in hopes of figuring out why AllJoyn will not pass it.

in that case it would still make since to send the Message object using your original interface. However you would have to change the message class. You could crate a structure to that is contained in your message class.

Create a MessageData class that can be introspected by AllJoyn.

public class MessageData {
    /**
     * Message Fields
     */
    @Position(0)
    @Signature("i")
    public int mMsgId;

   /**
     * Message payload
     */
    @Position(1)
    @Signature("ay")
    public byte[] mPayload
}

Then the MessageData can be part of the Message class.

public class Message {
    public static final int MESSAGE_LOCK_CAR = 0x01;
    public static final int MESSAGE_UNLOCK_CAR = 0x02;

    public MessageData mMsg;

    public Message(){

}

    public int getMsgId(){
        return mMsg.mMsgId;
    }
}

Make the interface take a MessageData:

@BusInterface (name = "com.carserverinterface")
    public interface CarServerInterface {
    public static String SERVICE_NAME = "com.carserverinterface";
    public static short CONTACT_PORT = 25;

    @BusMethod(signature = "i", replySignature = "y")
    Status sendMessage(MessageData msg) throws BusException;

    @BusMethod(signature="s", replySignature="b")
    boolean sendString(String string) throws BusException;
}

This would cause the sendMessage method to have a signature of "r" or "(iay)" this is a struct containing an integer and a byte array. When you pass a Java class to AllJoyn it uses intersection to search for the @Position annotations. Only member variables with the @Position ... (more)

edit flag offensive delete publish link more

Comments

Thanks for your response! This is indeed a good work-around, but I would like for my Message Object to have the opportunity to grow as needed. In the future, I may need to add more data into the Message Object and therefore this option would work.

mollyf ( 2015-04-23 16:07:06 -0700 )edit

(continued) The Message Object originally had a byte[] mPayload field in addition to the mMsgId field but I removed it to make the object simpler in hopes of figuring out why AllJoyn will not pass it.

mollyf ( 2015-04-23 16:08:10 -0700 )edit

The example in your Update Edit fails to register the bus object with an annotation error. This is the error I received originally which was only solved by adding annotation to the public static fields. When I add in the annotation to the static fields, your above code gets the same BusException

mollyf ( 2015-04-24 13:44:53 -0700 )edit

You may need to move the `MESSAGE_LOCK_CAR` and 'MESSAGE_UNLOCK_CAR' out of the class. I will mess with it a little. See if I can find something that could help you out.

georgen ( 2015-04-29 11:57:28 -0700 )edit

Thanks! For now I am using a solution that builds off of what you suggested and breaks the message apart before sending, then rebuilds it once received. It would be nice to know, though, why exactly the object itself cannot be sent

mollyf ( 2015-04-29 12:19:27 -0700 )edit
Login/Signup to Answer

Question Tools

Follow
1 follower

Stats

Asked: 2015-04-23 12:41:41 -0700

Seen: 116 times

Last updated: Apr 29 '15