Open boly38 opened 10 years ago
I have asked the jopt-simple project maintainer (https://github.com/pholser/jopt-simple/issues/65) to make its builds OSGi bundles, so probably from version 1.8 that will not be a problem. The libphonenumber project already had an issue (https://code.google.com/p/libphonenumber/issues/detail?id=205) for the OSGi support, hopefully that will also be supported soon (probably it worth adding a vote for it). I do not see the org.mozilla.javascript package among the imported packages, so probably that is not required to be modified. The
java.io.IOException: resource /draftv4/schema not found
at com.github.fge.jackson.JsonLoader.fromResource(JsonLoader.java:91)
problem hopefully be resolved by this issue.
hi firsrt of all thanks @aborg0 for this feedback +1:
and for the "schema not found" issue: I think this is related to json-schema-core project as draftv4/schema is included into the resource.
the problem hopefully be resolved by this issue.
sorry not sure to understand but what do you mean by "this issue" ?
regards
I thought you created this issue (#111) in order to get a solution to the resource not found problem,. (Using maven, a configuration is described here to add resources. Probably there is analogous for Gradle too.) Hmm. It seems it seems to be included in the jar. Probably classloading problem? I am going to try this out soon. Thanks.
Regarding the missing resources: I am not sure for the reason, but it seems the https://github.com/fge/json-schema-validator/tree/master/src/main/resources/draftv4 folder misses the hyper-schema file. (Though it is in https://github.com/fge/json-schema-core/tree/master/src/main/resources/draftv4, so changing the contextclassloader to the com.github.fge.json-schema-core
bundle's classloader (during JsonSchemaFactory.byDefault()
) solved this problem for me.) Is this the supposed workflow?
(It would be nice to also have OSGified services to get the required instances. Probably that was the purpose of this (#111) issue and I just misunderstood.)
@aborg0
yep, fixing "resource not found" pb should fix this issue. (a ready to use OSGi service would be perfect ^^). Sorry for the confusion, this is my fault. My english understanding is a little bit experimental :)
so changing the contextclassloader to the com.github.fge.json-schema-core bundle's classloader (during JsonSchemaFactory.byDefault() solved this problem for me.)
I make some time to switch again on this context and I'm not sure to understand. Could you tell me how you do that ? You patch the json-schema-core implementation ?
As Json validator end-user I used this to get a factory
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
Of course my side I use json-validator from a bundle B wich is different from json-schema-core bundle... do you mean I could workaround this "byDefault()" method ?
@boly38 I have to admit I do not prefer this solution -credits to Marcel Hanser whom I heard from-, but it works:
//find the bundle you need:
Bundle selected = null;
for (Bundle bundle: bundleCtx/**/.getBundles()) {
if ("com.github.fge.json-schema-core".equals(bundle.getSymbolicName()) selected = bundle;
}
ClassLoader specialClassLoader = selected.adapt(BundleWiring.class).getClassLoader();
....
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(specialClassLoader);
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
//Do something with the factory.
} finally {Thread.currentThread().setContextClassLoader(cl);}
So it does not require changes in the json schema validator code, though having OSGi services would make this a lot nicer.
Thanks @aborg0 I will test this tomorrow and give you a feedback. As second way, I would like to try too to remove draftV4 resources from json-schema-core as Cuong Tai do here..
Hi
here are my test results :
ClassLoader specialClassLoader = selected.adapt(BundleWiring.class).getClassLoader();
I could change this line to
ClassLoader specialClassLoader = selected.getBundleContext().getBundle().getClass().getClassLoader();
but I always got the same error.
Hope this helps If somebody found a better fix, please reply. Thanks again to you @aborg0 ^^
public class MyClassLoader extends ClassLoader {
Bundle b;
public MyClassLoader() {
super(MyClassLoader.class.getClassLoader());
}
public MyClassLoader(ClassLoader parent) {
super(parent);
}
public void setBundle(Bundle b) {
this.b = b;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return super.loadClass(name);
}//loadClass
@Override
public synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
return super.loadClass(name, resolve);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
return super.findClass(name);
}
@Override
protected URL findResource(String name) {
return super.findResource(name);
}
@Override
protected Enumeration<URL> findResources(String name) throws IOException {
return super.findResources(name);
}
@Override
protected Package getPackage(String name) {
return super.getPackage(name);
}
@Override
public URL getResource(String name) {
if (b != null) {
return b.getResource(name);
}
return super.getResource(name);
}
@Override
public InputStream getResourceAsStream(String name) {
return super.getResourceAsStream(name);
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
return super.getResources(name);
}
}//MyClassLoader
private JsonSchemaFactory getJsonSchemaFactory() {
// find the bundle you need:
String targetBundleSN = "com.github.fge.json-schema-core"; // "javax.mail.api"; // com.github.fge.json-schema-validator";
Bundle selected = findBundleBySymbolicName(targetBundleSN);
// Bundle selected = findFirstNotNullBundle();
if (selected == null) {
LOG.warn("unable to get bundle ");
return JsonSchemaFactory.byDefault();
}
// DO NOT COMPILE // ClassLoader specialClassLoader = selected.adapt(BundleWiring.class).getClassLoader();
ClassLoader specialClassLoader = selected.getBundleContext().getBundle().getClass().getClassLoader();
if (specialClassLoader == null) {
LOG.warn("specialClassLoader is null");
}
try {
URL resUrl = selected.getBundleContext().getBundle().getResource("/draftv4/schema");
LOG.info("bcontext get draftv4 resource ok :" + (resUrl != null ? resUrl.toString() : "(null)"));
}catch (Throwable t) {
LOG.info("bcontext get draftv4 resource KO : " + t.getMessage(), t);
}
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
// Thread.currentThread().setContextClassLoader(specialClassLoader);
MyClassLoader loaderToUse = new MyClassLoader(specialClassLoader);
loaderToUse.setBundle(selected.getBundleContext().getBundle());
Thread.currentThread().setContextClassLoader(loaderToUse);
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
// Do something with the factory.
return factory;
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
}
private Bundle findFirstNotNullBundle() {
Bundle selected = null;
Bundle[] osgiBundles = bcontext != null ? bcontext.getBundles() : null;
if (osgiBundles == null) {
LOG.info("unable to get context bundles");
return null;
}
for (Bundle bundle : osgiBundles) {
String bundleSN = bundle.getSymbolicName();
if (bundleSN != null) {
selected = bundle;
break;
}
}
if (selected != null) LOG.debug("bundle *found* => " + selected.getSymbolicName());
return selected;
}
private Bundle findBundleBySymbolicName(String targetBundleSN) {
Bundle selected = null;
Bundle[] osgiBundles = bcontext != null ? bcontext.getBundles() : null;
if (osgiBundles == null) {
LOG.info("unable to get context bundles");
return null;
}
for (Bundle bundle : osgiBundles) {
String bundleSN = bundle.getSymbolicName();
if (targetBundleSN.equals(bundleSN)) {
selected = bundle;
break;
}
// LOG.debug("bundle => " + bundleSN);
}
if (selected != null) LOG.debug("bundle *found* => " + selected.getSymbolicName());
return selected;
}
I just push a first draft of this : bundl'ized version of json-schema-validator
for rhino deps There is a MANIFEST.MF update required too : I think that related issue is github.com/mozilla/rhino #86
Following json-schema-validator-bundle creation and from my point of view, this issue could be closed. ^^
@boly38 thanks a lot for this work, I'll have a look at it; to be honest, OSGi has never been a priority for me and I haven't researched the subject enough to come with a viable solution...
I'll try and understand your work; ideally, I want this to be part of the main distribution although I cannot figure out how to do this yet...
@fge @boly38 I think the ideal case would be to include OSGi services as well as SPIs* (and not using classes getResource from other bundles). That way we would be sure that there are no classloading problems. (My colleagues reported that they had problems with org.mozilla.javascript's Rhino latest version, so we use the 1.7.2 version from eclipse orbit. Fortunately as it is not a bundle on maven central the restriction on the maven version is not present for this in the schema validator bundle.) Thanks for checking. I am sure @boly38 did a great job to make things work, although I think that way we lost a significant amount of modularity (it is hard to replace the inlined bundles). Unfortunately I'll be too busy for the rest of this year to contribute for a better solution (which imho would involve declaring OSGi services).
*: For OSGi R5 aries SPI fly is also an option, but we are currently on OSGi R4.
OK, the thing is that I am not very knowledgeable with OSGi; I cannot fully understand the problems at hand, and even if I do I wouldn't know how to fix them properly in the first place.
I would need guidance on how to approach the problems: what they are exactly, how to fix them; and one step at a time.
More particularly, I would appreciate a way to "unit test" correct OSGi usage. @boly38 @aborg0 is this doable?
@fge @aborg0 I understand your need to get a way to "unit test" correct OSGi usage. I used OSGi since 7 months only, on my project I make some unit tests out of OSGi box, and high level integration tests with my OSGi (non free) platform [impossible to share here].
I never look in detail how to do some kind of "OSGi layer only" integration tests.
Maybe by using OSGi framework like equinox or karaf it's possible to do that with a minimal effort but in the next week I have no time to spend on this. Sorry.
(need to be confirmed by an OSGi expert..) any way OSGi fwk let the way to use different versions of the same package. For example, if you would like to use json-validator bundle and one of the dependency (eg. jackson; inlined or not) with a different version for your need, then you could also make the good osgi import package definition in your own bundle to do that. As CL are separated you wont get class loading issue.
@fge I think these kind of integration tests are best done by creating a new test project (depending on the original) and execute the tests there using an OSGi container like equinox, knopflerfish, felix or something else. (You need to make all dependent bundles available for the framework, I think the tycho project might help in this regard.)
Hi all, I was trying to integrate json-schema-validator as an OSGi bundle and I took so many time to do that. I create a post to explain this : [1].
Please could you check again the OSGi compatibility and tell me if I'm wrong.
[1] http://curiositedevie.blogspot.fr/2014/08/use-json-schema-validator-as-osgi-bundle.html