Skip to main content

[JXSE 2.6] and Equinox

16 replies [Last post]
keesp
Offline
Joined: 2007-05-22
Points: 0

Hi,

I have just started to implement JXSE 2.6 as an equinox bundle, and I am running into some problems when I start the network manager. It throws an exception from the net.jxta.id.IDFactory (see below).

Apparently the IDFactory is missing the bundle "net.jxta.impl.config" for the locale that I'm using (nl-NL).

What is the recommended approach to resolve this problem?

Thanks

Kees

java.lang.IllegalStateException: Could not initialize ID defaults
at net.jxta.id.IDFactory.(IDFactory.java:636)
at net.jxta.id.IDFactory.(IDFactory.java:127)
at net.jxta.platform.NetworkManager.(NetworkManager.java:156)
at net.jxta.platform.NetworkManager.(NetworkManager.java:172)
at org.condast.jxse.Activator.start(Activator.java:20)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl$1.run(BundleContextImpl.java:783)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.startActivator(BundleContextImpl.java:774)
at org.eclipse.osgi.framework.internal.core.BundleContextImpl.start(BundleContextImpl.java:755)
at org.eclipse.osgi.framework.internal.core.BundleHost.startWorker(BundleHost.java:352)
at org.eclipse.osgi.framework.internal.core.AbstractBundle.resume(AbstractBundle.java:370)
at org.eclipse.osgi.framework.internal.core.Framework.resumeBundle(Framework.java:1068)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.resumeBundles(StartLevelManager.java:557)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.incFWSL(StartLevelManager.java:464)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.doSetStartLevel(StartLevelManager.java:248)
at org.eclipse.osgi.framework.internal.core.StartLevelManager.dispatchEvent(StartLevelManager.java:445)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:227)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:337)
Caused by: java.util.MissingResourceException: Can't find bundle for base name net.jxta.impl.config, locale nl_NL
at java.util.ResourceBundle.throwMissingResourceException(Unknown Source)
at java.util.ResourceBundle.getBundleImpl(Unknown Source)
at java.util.ResourceBundle.getBundle(Unknown Source)
at net.jxta.id.IDFactory.(IDFactory.java:629)

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
keesp
Offline
Joined: 2007-05-22
Points: 0

As I've become more acquainted with this issue and would propose a simpler solution than what I suggested earlier. I've posted the message below earlier, and now I would like to suggest to implement this. I've been working with this minor refactoring strategy in equinox and felix, and as far as I know it should work in all other cases too...

Could it be possible to implement this in an upcoming release? It would take one problem away from Equinox-JXSE integration, and some other environments as well.

>The problem is that the following code does not work correctly in Equinox, due to >differences in class loading:

>ResourceBundle jxtaRsrcs = ResourceBundle.getBundle("net.jxta.impl.config");

>As far as I can see, the following code will achieve exactly the same:

>InputStream in = this.getClass().getResourceAsStream("/net/jxta/impl
>/config.properties");
>PropertyResourceBundle jxtaRsrcs = new PropertyResourceBundle( in );

>Provided of course that the loaded resources are property resources. I have checked >the code and found that resource bundles are found in twelve files:

>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\id\IDFactory.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\impl
>\cm\XIndiceAdvertisementCache.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\impl\endpoint
>\endpointMeter\ConditionalEndpointMeterBuildSettings.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\impl\endpoint
>\tls\TlsTransport.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\impl\endpoint
>\transportMeter\ConditionalTransportMeterBuildSettings.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\impl\meter
>\ConditionalMeterBuildSettings.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\impl\rendezvous
>\rendezvousMeter\ConditionalRendezvousMeterBuildSettings.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\impl\resolver
>\resolverMeter\ConditionalResolverMeterBuildSettings.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\peergroup
>\NetPeerGroupFactory.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\peergroup
>\PeerGroupFactory.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\platform
>\NetworkConfigurator.java
>D:\projects\incubator\workspace\jxta\net.jxta.26x\src\net\jxta\util\ClassFactory.java

>These point to two files, either config.properties or user.properties, which I believe are >both properties files. The ClassFactory provides a convenience method and does not >need to change, as far as I can tell.

.>As a result, I would propose to change all the references to these resource files with >the alternative using an inputstream. I think this would have no effect on the code in >other development environments, and would improve the compatibility with >Eclipse/Equinox. I have tested this with IDFactory, netpeergroupfactory, >peergroupfactory and networkconfigurator, and it seems to work okay. If I need to test >the other occurences, I would need to have some test examples, as I am not very >up-to-date with metering issues, but I would think that in itself the proposed change is >very minor.

>If there is anything I can do to support this change please let me know!

Cheers

Kees

keesp
Offline
Joined: 2007-05-22
Points: 0

...by the way...

This will not resolve jxse with android, as I've understood that Android actually moves the config files to another location in a maven-kind of fashion. It might be worth considering to take the same approach with a following JXSE release. In that case I think the properties files should be collected in a resources subdirectory somewhere under the root of the JXSE jar file. See

http://forums.java.net/jive/thread.jspa?messageID=478801&tstart=0

for details

Cheers

Kees

keesp
Offline
Joined: 2007-05-22
Points: 0

I've just worked through all the classes that load resource bundles. The solution I have come up with, with help of Jérôme, works well (see above), but would need a bit of refactoring in a future release.

In short, I've made a resource bundle loader (singleton) that makes it possible to load resource bundle prior to starting the network manager. If not, the default load policy is used. From what I can currently oversee, only the user,properties and config.properties are currently used, in the following classes: NetworkConfigurator, PeergroupFactory (deprecated method), NetPeergroupFactory, XIndiceAdvertisementCache, TlsTransport, IDFactory and a number of MeterBuildThingies (I'm not quite sure what these do). In these files, the ResourceBundle.getBundle(str) would have to be replaced by ResourceBundleLoader.getBundle(str), which is fairly innocent approach.

I plan to test this in netbeans (for the default behaviour), and also hope to see if I can make the changes work for Felix and knopflerfish. If I have done that and it seems to work okay, then I will advice to take the changes up in the next release.

Does that sound like a useful approach?

Kind regards

Kees

keesp
Offline
Joined: 2007-05-22
Points: 0

Hi Jérôme,

I would like to posit an idea for the problem that I mentioned earlier. You solution is not going to work, because the problem with Equinox is a bit more fundamental; I need to use an entirely different way of getting access to the properties files. Because this is needed more often, I got the feeling that it would be better to expand your idea not to the properties file, but to a Map with resourcebundles that is configured as a singleton. The corresponding class ResourceBundleLoader has been attached.

This loader will check to see if a resource bundle exists, and if not will try to get it with the default approach. If a resource is already loaded, it will use that one instead. The IDFactory has been modified as follows:

ResourceBundle jxtaRsrcs = ResourceBundleLoader.getBundle("net.jxta.impl.config");

And the GetBundle method is:

/**
* Implements a default strategy to load a bundle for the given key, where the key represents the location
* of the bundle.
*
* Get the bundle associated with the given key from the loader, or find it.
* @param key
* @return
* @throws MissingResourceException
* @throws IllegalStateException
*/
public static ResourceBundle getBundle( String key ) throws MissingResourceException, IllegalStateException{
ResourceBundleLoader loader = ResourceBundleLoader.getInstance();
if( loader.contains( key ))
return loader.getResource( key);
ResourceBundle resource = ResourceBundle.getBundle(key );
loader.put( key, resource);
return resource;
}

Now I can start a resourcebundle loader in the Activator of Equinox and use the standard Equinox approach to load the bundle. If, a bit later on, another bundle calls the network manager, it will find a resource already present and use that one.

With this, a relatively minor modification in JXSE 2.6 could be possible in order to prepare it for Eclipse/Equinox, while JXSE will work in the regular way in other environments.

what are your thoughts?

Thanks

Kees

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

Looks fine to me. I understand that we have to update the code to use this class's static method, correct?

If you have a patch, can you attach it to https://jxta-jxse.dev.java.net/issues/show_bug.cgi?id=367 ? If you don't have proper access, attach it here and I'll put in the incident. Please make the patch against the 2.6 branch.

Thanks.

keesp
Offline
Joined: 2007-05-22
Points: 0

Ok,

I will do some more tests and prep the code for inclusion in JXSE. I would opt for a gradual approach, and only change access to the various properties files when I run into them, instead of reimplementing the whole JXSE code in one go. I'd prefer to do some rigorous testing on small changes that I run into, rather than making changes in areas that I know little about ;)

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

OK. In that case, may be we are better off waiting for the Cheeseburger branch to open. I guess it will be easier, unless you absolutely need something out now for 2.6.

keesp
Offline
Joined: 2007-05-22
Points: 0

nope, I'm ok just as it goes. I've got no problem waiting for a next phase

keesp
Offline
Joined: 2007-05-22
Points: 0

Hi AdamMan71,

I am seeing where the problem is, I should have been a bit more alert yesterday...
The problem is that resources are accessed a bit differently in equinox bundles, which means that the hard-coding of the location in IDFactory (and elsewhere) will fail when JXSE is deployed as an equinox bundle.
In equinox, the location will be [my.equinox,bundle.name].net.jxta.impl.config.properties.

I will need to access this file through a getEntry(..) method provided by Equinox, with the result that I shall have to load the file first, and then access the IDFactory.

I am building JXSE as an equinox bundle using the source code, so if you can provide a hint on what the best way is to approach this, then I can code this tomorrow and test it. Probably the best way to approach this is to first load the file using the default equinox method calls, and then starting the network manager with this file as an argument.
however, this approach will have to used for all the resources that are used, and are packed in the jar-file, and that might cause some major refactoring of the code.
I do think that on hte long run, this might make JXSE more versatile though.

any ideas?

Thanks

Kees

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

Hi Kees,

Ok, now I understand your issue better. The solution that comes to my mind is the following:

1) We create a Class C (or any other name) containing static final attributes pairs such as:

public final String ConfigProp_Default = "net.jxta.impl.config.properties";
public final String ConfigProp_Key = "ConfigProp_Key";

2) Everywhere we use "net.jxta.impl.config.properties" in the code, we replace it with:

System.getProperty(ConfigProp_Key, ConfigProp_Default);

3) Assuming that this is possible for Equinox (but I am no expert with it), you could set a value for ConfigProp_Key early in the code like this:

System.setProperty(ConfigProp_Key, "[my.equinox,bundle.name].net.jxta.impl.config.properties")

As a consequence, 2) will return "[my.equinox,bundle.name].net.jxta.impl.config.properties" if it is set for the key, or "net.jxta.impl.config.properties" (default) if not.

This could be a quick fix. Do you think it would work on your side?

I have noticed that there were many other places using ResourceBundle. I have been trying to refactor the code to get rid of these, but I step on bugs after bugs... I does not seem like an easy one at all, so if the above trick works...

Let me know what you think !

Jérôme (AdamMan71)

keesp
Offline
Joined: 2007-05-22
Points: 0

Hi Jérôme,

Good idea! I will try to test this idea tomorrow, but there is a chance that it may fail if equinox has some other issues with the resource bundle approach, that I still need to look into. It certainly is a better solution to the hack I am trying now.

My idea is to create a fully functional JXSE bundle step by step, and report what I run into. It may be of help to guide some architectural decisions the team may be dubbing on.

Cheers

Kees

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

OK great, let me know the oucome !!! If it needs a lot of rework, I'd rather that we push this to the next release, because right now, I am trying to polish 2.6. If the patch is small enough, then we can still include it in 2.6.

About Equinox, 2.6 can be started from an OSGi context. I have used Felix for that, but I believe this would work with Equinox too. Loading JXTA services via OSGi is of course the holy grail, but IMHO, we still need to cleanup some code, get rid of the current JxtaLoader implementation and refresh the JXTA specs...

Jérôme (AdamMan71)

keesp
Offline
Joined: 2007-05-22
Points: 0

I agree with you. I think the 2.6.x version is best served with good solutions and as few hacks as possible. A number of these changes may also take a while.

I'll keep you posted

Kees

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

Hi Kees,

I have created a patched .jar available at http://kenai.com/projects/jxse/pages/26BetaRel. Can you check it on your side?

I have replaced the code with:

// Get our resource bundle
URL TempURL = IDFactory.class.getResource("/net/jxta/impl/config.properties");
Properties props = new Properties();
props.load(TempURL.openStream());

Thanks,

AdamMan71

keesp
Offline
Joined: 2007-05-22
Points: 0

I will look try it out tonight or tomorrow and keep you posted.

thanks for the quick response

Kees

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

Hi Kees,

I googled a little and found the following: http://javahowto.blogspot.com/2006/05/debug-java-util-missingresourceexc....

I believe the comments at the bottom of the articles says it all. I'll try to craft a solution for this. Stay tunned (as they say).

AdamMan71