0

I'm working with a knopflerfish environment where I am trying to use functions from a remote object using ServiceRegistration. I will explain as an example. I have created two bundles, A and B. Bundle B has a class C where I have implemented two methods:

public void printIt(JSONObject toPrint) {
    logger.debug(toPrint);
}

public void printIt(String toPrint) {
    logger.debug(toPrint);
}

public JSONObject returnedJ() {
    return (new JSONObject());
}

public String returnedM() {
    return "hello";
}

This class C is being initializated in B's activator and registered using ServiceRegistration so it can be used as a remote object from bundle A. A's activator just gets the registrated object C in order to use it's methods and here is where the problem appears. The remote object can be used but only methods that use String are working the JSONObject ones don't. Has this happened to anyone? Which could be the explaination?

I have tested this behaviour debuging and using try/catch and no errors are shown. Also have to say that when using JSONObject methods bundle A gets frozen and there is no signal in the method from class C. For now I will be parsing the objects from JSONObject to String in bundle A and from String to JSONObjects in bundle B but this is still annoying me.

PD: im using org.codehaus.jettison.json.JSONObject.

Thanks in advance.

xian
  • 3
  • 2
  • Please clarify the error you are seeing. You said that the methods that use JSONObject "don't work". But you also said there is no error shown. So how do you know it didn't work? Be specific about what you expected to happen, and what actually happened. – Neil Bartlett Jan 15 '19 at 15:53
  • When I use try/catch sentence with a general Exception (where the funtion is called and inside the function) there is no error shown on either bundle. The content of the function on bundle **B** using JSONObject never executes (tried to put a print in there) and the return never reaches bundle **A** also when bundle **A** gets to that line it gets frozen so the following code in that bundle don't even execute (I put some prints arround to test it). My supposition is that the remote object system from knopflerfish don't allow JSONObject... Sorry for the lack of clarity, its my first post here. – xian Jan 16 '19 at 07:21
  • When you say "remote object system" do you actually mean remote? As in, calling over the network using some kind of RPC? – Neil Bartlett Jan 16 '19 at 07:37
  • No, I'm talking about the ServiceRegistration where you can register an instance from an object part of a bundle(in this case class **C** from bundle **B**) and then access that object instance from another bundle, sorry for the missunderstandment but I have worked with remote objets while using RMI and this reminds me a lot of its behabiour. – xian Jan 16 '19 at 09:06
  • Okay so there is no actual remoting... good, that makes things simpler. I suspect that you are simply missing an import for the `org.codehaus.jettison.json` package and that you are swallowing the NoClassDefFoundError (or ClassNotFoundException). It's impossible to say more without seeing the code. – Neil Bartlett Jan 16 '19 at 09:09
  • I'm importing `org.codehaus.jettison.json.JSONObject;` in both bundles (a copy of the same lib) instead of exporting it from a bundle. I'll try to export it and see what happens. I'll be right back. – xian Jan 16 '19 at 09:32
  • That was the problem, it looks like the lib was not identified as the same on both bundles so it wasnt working. Once I starting using _Exported Package_ of `org.codehaus.jettison.json.JSONObject` in one bundle and _Imported Package_ on the other everything went ok. I dont know how to proceed about the answer, would you answer the question or should I do it? By the way thank you very much! – xian Jan 16 '19 at 09:56
  • Ah okay. Never copy shared libraries into bundles! At runtime the identity of a class in Java is the fully qualified name PLUS the classloader that loaded it. Therefore you had two classes named `JSONObject` which Java believed to be entirely different classes, and it would have thrown a ClassCastException to use one where the other was expected. – Neil Bartlett Jan 16 '19 at 10:06
  • Perfect then. As im new here, what should i do with the answer? Should it stay as a comment? Is it possible to rate it or mark it as problem solved? – xian Jan 16 '19 at 10:20
  • I will copy the relevant details into an answer, which you can accept if you like. – Neil Bartlett Jan 16 '19 at 15:47

1 Answers1

0

In comments, questioner clarified that the library providing the org.codehaus.jettison.json.JSONObject type had been copied/embedded into both bundles.

Embedding can be used for libraries that are used entirely within a bundle, but never for types that might be shared between bundles, e.g. as part of an API. This is because, in Java, the identity of a type is the combination of its fully qualified name and the classloader that defined it. Therefore, the type JSONObject defined by one bundle is different from the type JSONObject defined by another bundle – even if they identical in terms of bytecode. If you were to try to load an instance of one into a variable that is expecting the other, you would see a ClassCastException with a message of the form "JSONObject cannot be cast to JSONObject".

The solution is to ensure that the library is only present and exported in one bundle, and imported by all other bundles that use it.

Neil Bartlett
  • 23,743
  • 4
  • 44
  • 77