Skip to main content

Question about multiple instances of the world peer group

16 replies [Last post]
adamman71
Offline
Joined: 2007-01-31
Points: 0

Hi,

When I take a look at the code, there is an explicit restriction preventing the creation of multiple world peer group instances in the WorldPeerGroupFactory. Something similar is implemented in the NetPeerGroupFactory.

My question is: is this restriction purely functional or is there a technical reason behind this? If there is a technical reason, what is it?

Thanks,

J.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
adamman71
Offline
Joined: 2007-01-31
Points: 0

Hi Mike,

Even when I create my own ClassLoader based on the PeerClassLoader.class from the bench project and compile it into a .jar file on a separate project, I still get a lot of this GhostBusters issue.

The only objects that the instances of the PeerClassLoader share in common (together with my main class trying to create several peers) are system classes. Therefore, all JXTA objects are coming from their own space and cannot be assigned to each other, since they have been loaded by different class loaders.

One can instantiate some local space JXTA objects using the shared system classes, but unfortunately, it is not enough to bootstrap peers in their local space. No matter if you try by the NetworkManager, the NetworkConfigurator and the NetPeerGroupFactory, for example, you are stuck at some stage because of the Ghostbusters issue.

Let's assume that a main class having access to the delivered JXTA .jar files tries to load two peers from different class loaders who load their JXTA objects from the provided location, how do you get the main class to set/control the configuration that each peer should have?

I have searched in the code of the bench for usage of the PeerClassLoader, but it is not used anywhere in the link you have posted. So, I am wondering where I can find the examples using these PeerClassLoaders to load multiple peers in the same JVM? Are there other links?

P.S.: I was thinking about crossing the streams just a little by extending the set of class each class loader has in common, but is that a good idea?

Thanks,

J.

P.S.: As my grand grand grand grand grand grand grand grand grand grand father, the Marquis de Sade used to say: "[i]JXTA is not a torture, it is a pleasure![/i]"

bondolo
Offline
Joined: 2003-06-11
Points: 0

> Therefore, all JXTA objects are coming from
> their own space and cannot be assigned to each other,
> since they have been loaded by different class
> loaders.

Yep, that's the intent.

> No matter if you try by the NetworkManager,
> the NetworkConfigurator and the NetPeerGroupFactory,
> for example, you are stuck at some stage because of
> the Ghostbusters issue.

Interacting with static methods on classes loaded in sub-class loaders is really difficult because the methods are only available via reflection. You cannot use the "Class.method()" syntax to call static methods because that assumes that the class is loaded in to the same class loader as the calling code.

At the time the PeerClassLoader was created none of the current configuration and network management infrastructure existed. I believe that configuration was done exclusively through the old configuration UI (which is why there aren't any samples).

adamman71
Offline
Joined: 2007-01-31
Points: 0

My Lord, I have tortured myself more today :D and have managed to make two peers connect in the same JVM (an EDGE connects to a RDV), but the method to perform this is more sophisticated than what has been described until now.

Here is how to proceed:

i) Create 5 classes called: Main, BigBang, Peer_EDGE, Peer_RDV and ProtonStream in the same project.
ii) Peer_EDGE and Peer_RDV must inherit of BigBang, which is an empty class having only a constructor with no parameter.
iii) The constructor of Peer_RDV creates an RDV peer via the NetworkManager and sets proper configuration.
iv) The constructor of Peer_EDGE creates an EDGE peer via the NetworkManager and sets proper configuration, including setting Peer_RDV as a rendezvous.
v) ProtonStream is a class based on the PeerClassLoader.class (a class loader) available from the bench project. One can remove the code regarding Log4j. One should implement the Runnable interface in this class too. Add a method called BootStrap(String PeerClassName) taking a String parameter. This method should load an instance of ProtonStream itself, retrieve the constructor and invoke an instance by passing the paths to the the .jars files we will mention later. Create a new thread using this instance and set the thread's name to PeerClassName. Then start the thread.
vi) The run() method of the ProtonStream should start by retrieving the name of the current thread. Then it should load the peer using the corresponding class name that we have retrieved from the current thread's name, using the current ProtonStream. Extract the constructor (this is where you will understand why the BigBang class is necessary). And start an instance, which is an instance of the desired peer. It is easier when Peer_RDV and Peer_EDGE have a constructor with no parameters.
vii) The Main class only creates a new ProtonStream by providing the path to the .jars that we will discuss later. Then it calls the bootstrap method of this ProtonStream by providing the class name of Peer_RDV and Peer_EDGE, which will trigger the creation of the two peers without crossing the streams.
viii) At last the .jars... Compile the project containing the 5 classes and copy the resulting .jar and the delivered JXTA .jar into a separate directory. The paths to the jars in this directory will have to be provided by the Main class to the first instance of the ProtonStream, and these paths have to be provided by this ProtonStream to the child ProtonStream its creates in the BootStrap method.

This work, but it is slow to take-off... The ProtonStreams spend their time scanning the .jars files at the beginning !!!

Those who have read all the messages of this thread and who have managed to make two (or more) peers work in a single JVM can click on the following link: http://youtube.com/watch?v=ztTVWvtG9Ec (the others should torture themselves a little more...)

J.

adamman71
Offline
Joined: 2007-01-31
Points: 0

I have performed some research, but even if I try to load world peers groups from separate class loaders, the GenericPeerGroup.class performs a check on created instances via the following code in the initFirst() method:

[i]if (!globalRegistry.registerInstance((PeerGroupID) assignedID, this)) {
throw new PeerGroupException("Group already instantiated");
}[/i]

and of course an exception is thrown when the second world peer group is created, because an instance has already been registered in the global registry by the first instance.

Unless this class is modified, I don't see how this way of proceeding (i.e., using multiple class loaders) can work.

If someone was kind enough to take care of the links on the bench project to let everyone access the code examples, that would help.

Thanks,

J.

bondolo
Offline
Joined: 2003-06-11
Points: 0

> I have performed some research, but even if I try to
> load world peers groups from separate class loaders,
> the GenericPeerGroup.class performs a check on
> created instances via the following code in the
> initFirst() method:
>
> [i]if (!globalRegistry.registerInstance((PeerGroupID)
> assignedID, this)) {
> throw new PeerGroupException("Group already
> instantiated");
> [/i]
>
> and of course an exception is thrown when the second
> world peer group is created, because an instance has
> already been registered in the global registry by the
> first instance.
>
> Unless this class is modified, I don't see how this
> way of proceeding (i.e., using multiple class
> loaders) can work.

You're not torturing yourself enough. :-) The problem is that the WorldPeerGroupFactory class you are using is not the one from the private class loader.

1) start by removing jxta and all of the dependent jars from your classpath. This will prevent any unintentional references.

2) for each peer instance construct a new url class loader who's parent is your class loader. Main.class.getClassLoader()

3) Add jxta.jar and all of the dependent jars to the path of the URLClassLoader you just made.

4) Get a class reference to the WorldPeerGroupFactory or NetPeerGroupFactory class from the url class loader via findClass()

5) use reflection to get the appropriate factory method on the WorldPeerGroupFactory.

6) call the method. The group object returned will be specific to the url class loader.

7) you can now repeat steps 2) through 6) for as many peers as you need.

8) for each PeerGroup which results from 6) you will find that pg.class.getClassLoader() will be different.

9) As they say in "Ghostbusters", "Don't cross the streams!" Take great care to make sure that all references to jxta objects which are instantiated from one class loader never ever mix with jxta objects which are from another peer. This means you can't (directly) publish an advertisement to multiple groups, reuse an id object, etc. All references to jxta objects should be isolated such that there is no possibility that objects created in different class loader contexts come into contact.

> If someone was kind enough to take care of the links
> on the bench project to let everyone access the code
> examples, that would help.

https://jxta-benchmarking.dev.java.net/source/browse/jxta-benchmarking/

Mike

adamman71
Offline
Joined: 2007-01-31
Points: 0

About point 4), the call to findModule() can be made by passing a string corresponding to NetPeerGroupFactory.class.getName(). Therefore, I can meet the requirements of point 1.

But point 6) supposes that you know about peer groups, no? How can I write some code without having access to the delivered JXTA .jars? I need to import the definition of a peer group, no? How can I work this around?

This is a torture, I agree :-) !

J.

bondolo
Offline
Joined: 2003-06-11
Points: 0

You need to include the JXTA jars in the classpath for development in order to compile correctly. I was just suggesting removing the jars from the system classpath because their presence might produce confusing results.

To use NetPeerGroupFactory.class.getName() requires loading of the class within the system class loader. This is contrary to your purposes. I would instead use the explicit string in this particular case

ivarulz
Offline
Joined: 2007-08-17
Points: 0

My approach was:
- stop and unreference all groups after registration
- create a new NetworkManager and start the network again

Problem: it won't connect to the RDV anymore.
Basically the same code is running for registration and connect, but before connect, the jxta platform is cleaned up.

adamman71
Offline
Joined: 2007-01-31
Points: 0

Hi ivarulz,

Running multiple peers in the same JVM is tricky and requires juggling in a tortuous way with Java concept and code. It would be impractical to try to find a solution based on this. JXSE has not been developed with this in mind.

I am a bit confused when you mention a peer name, because peer recognize each other using peer ids. If you build your peer ID based on a name, then your peer id will not change each time you connect to JXTA. What information are you exactly fetching during the registration and what do you do with it after?

Now, the reason why you don't connect to your RDV anymore might be because you clean your platform, including any registered seeds. Therefore, when you restart JXTA, your peer can't locate your RDV anymore, since the corresponding seed might be missing.

Cheers,

J.

ivarulz
Offline
Joined: 2007-08-17
Points: 0

Thanks man,

The functional requirements impose a unique peer name in the private network. We have a "server" peer which manages the peer names.
A registering peer chooses it's own peer name and the server peer just checks that no other peer got that already.

I found a solution that suits my needs: since the peer name is just used for adv publishing and search, i just start another peer group and publish advertisements about the peer using the new peer name instead of the temporary peer name used for registration ("tempRegistrationPeer").

So far so good.

ivarulz
Offline
Joined: 2007-08-17
Points: 0

Dear J,

I would really need a hint on the following, since you already were successful on running 2 peers in the same JVM.

We have an application that requires remote registration, which is performed using jxta.

So, for registration we use a TempPeerName for sending registration data to a power peer.
Immediately after registration, the user connects to the group, but this time using the username he provided "John" as peer name.

Question: do you have an idea on how to replace on the fly the TempPeerName with John, such that the advertisements are published/found correctly?

Thank you

adamman71
Offline
Joined: 2007-01-31
Points: 0

Viva la JXTA !!!

bondolo
Offline
Joined: 2003-06-11
Points: 0

There's no reason to ever have more than one instance of the WorldPeerGroup so the factory ensures that it is used as a singleton and only a single instance is ever created.

This is not the case with the NetPeerGroup. It is possible to have more than one instance of the NetPeerGroup. Commonly only a single instance is used which, to make the NetPeerGroupFactory easier to use, is the default offered by the factory. For an example of how to use the NetPeerGroupFactory to create multiple network peer groups see :

https://jxta-jxse.dev.java.net/source/browse/jxta-jxse/trunk/tutorials/s...

adamman71
Offline
Joined: 2007-01-31
Points: 0

I was thinking about having multiple instances of a peer in the same JVM. In an earlier thread, you mention that it is possible to achieve this by using multiple class loaders, which is what I am trying to do.

Am I correct when I say that in that case, one has to create two (or more) instances of the world peer group coming each from different class loaders? Is that the only way to proceed?

Thanks,

J.

P.S.: The links in the https://jxta-benchmarking.dev.java.net/ webpage are broken.

bondolo
Offline
Joined: 2003-06-11
Points: 0

> I was thinking about having multiple instances of a
> peer in the same JVM. In an earlier thread, you
> mention that it is possible to achieve this by using
> multiple class loaders, which is what I am trying to
> do.
>
> Am I correct when I say that in that case, one has to
> create two (or more) instances of the world peer
> group coming each from different class loaders? Is
> that the only way to proceed?

Yes. If you want multiple JXTA JXSE peer instances in a single JVM then multiple class loaders is the ONLY workable approach. The JXTA JXSE implementation includes several singleton classes that preclude instantiating multiple peers within the same class loader. Yes this is probably inconvenient for some but for most applications it actually makes things simpler. It's also very difficult to turn back the clock 8 years to fix the implementation as the singleton pattern has been used extensively within JXSE since the very beginning of JXTA.

> Thanks,
>
> J.
>
> P.S.: The links in the
> https://jxta-benchmarking.dev.java.net/ webpage are
> broken.

Unfortunately the benchmarking project currently lacks a maintainer to fix the broken links. The project is currently seeking a new maintainer.

adamman71
Offline
Joined: 2007-01-31
Points: 0

Many thanks, it is good to know that I am on the right track.

Cheers,

J.