cancel
Showing results for 
Search instead for 
Did you mean: 

inqmyxml.jar exclusion

Former Member
0 Kudos

Hello,

for some special reason (maybe every reason in special....) I want to use my own XMLPARSER API. So I want to get rid of the build-in-xmlinqmy.

The inqmy in not in the Sharingreference!

But for some reason it is load anyway. So how can I use my own XML-jar in the lib folder??

Your answer would be highly appreciated.

Walter

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Hello Walter,

Unless I'm missing something it should be pretty simple. For example, I'm currently working on something needing the Jakarta-RegExp library. All I had to do to use the library was to put it in the dist/PORTAL-INF/lib folder, and reference this .jar in the project build path. The same thing should work for using an XML parser API.

Former Member
0 Kudos

Hello,

I'm using jakarta Digester for some XML belongings....

Digester needs a XML parser. Some Classes are loaded dynamicly so I have no influence on that.

If I use a different parser than inqmyxml everything works fine and I get no errormessage* but somehow the inqmyxml parser is loaded for this even if I have another one in the lib folder.

*tested in a application run by a main method

Walter

detlev_beutner
Active Contributor
0 Kudos

Hi Walter,

you're putting the finger on the wound...

InQMy.xml is a J2EE server's base library, to be found under additional-lib of the server. It is referenced to irj application, so that it is put within the classpath of everything under irj. That's the reason why you catch it even if you didn't reference it explicitely.

We have two spots of trouble here: the inqmy implementation (not consistent for example with xerces; bugs are on both sides) as well as the classloader.

The classloading problem is the following: Classloaders are expected first to look up within their hierarchy before looking for the class on the same level. This means that first the root is checked, and then down the tree. For inqmyxml is quite up within the tree, it gets loaded even if you add Xerces for example at portal app level.

This is a known problem with the Java classloading strategy, but the strategy within other fields is good.

For this reason, the ThreadContextClassloader has been introduced. It's just like a ClassLoader mapped to a thread so that every application can catch a specific classloader.

Two possible solutions: (a) Is it possible that Digester uses the ThreadContext classloader? If yes, you can set the ThreadContextClassloader before calling Digester. The problem here is, that the portal is not free of using the ThreadContextClassloader, so you would have to set it back afterwards (it's a design mistake within the portal). (b) Maybe it is possible to pass a concrete classloader to Digester?

Hope it helps

Detlev

Former Member
0 Kudos

Hello Detlev,

once again, thanks a lot for Your reply.

One more (maybe trivial question):

I can set a classloader. But what step is next?

Do I have to pass the Portalclassloader??

E.g.

 PortalRuntime.class.getClassLoader(); 

Thanks

Walter

detlev_beutner
Active Contributor
0 Kudos

Hi Walter,

> I can set a classloader

Great! Imagine yourself being one of the happiest men in universe! (While I'm on the sad side, using Hibernate - they just play with ThreadContextClassloaders... ).

OK, now up to the next step.

All you want to pass to Digester is a classloader which brings up Xerces or similar (and maybe some more).

Each existing classloader in your portal world is a child of the J2EE's classloader for IRJ application - with inqmyxml.jar in it.

So you will have to write your own classloader (if there isn't a classloader within the portal violating the classloading hierarchy; such a classloader you could use directly).

The easiest way probably would be to write your own classloader as a child of the system classloader. No more inqmyxml within the hierarchy. Decompiling a portals classloader my help. It's not that easy if you haven't done this before, but I'm positive you'll do it (and you will learn much about classloading, a very nice side effect).

Hope it helps

Detlev

Former Member
0 Kudos

> It's not that easy if

> you haven't done this before, but I'm positive you'll

> do it (and you will learn much about classloading, a

> very nice side effect).

Your believe in me strengthens my self-assurance!!!

Thanks

Walter

Former Member
0 Kudos

Remember doing something like this a few years ago.

There is a class in the java api called URLClassloader to which you give as an in parameter an array of URL objects (which you create from a File object pointing to the location of your xerces.jar)

As far as I remember, it shouldn't ask the system classloader for anything

detlev_beutner
Active Contributor
0 Kudos

Hi Dagfinn,

sorry, this is not right. The Java classloading policy has been bottom up first, then changed to top down, and for all the complications with this the ThreadContextClassLoader has been introduced in 1.2.

So all Classloaders offered by Sun follow the new policy, to quote from URLClassLoader: "after first searching in the parent class loader".

Nevertheless, you are free to implement your own classloader violating this policy.

Best regards

Detlev

Former Member
0 Kudos

Hi,

Did some testing (and looking at the java source) and it seems to work if you give send in null as the parent classloader in URLClassloader

I made a small program which includes apache ant in the classpath when running.


URLClassLoader classLoader = new URLClassLoader(new URL[]{new File("c:\wasutil.jar").toURL()},null);

//this loads a class from the wasutil.jar
Class c1 = classLoader.loadClass("com.statoil.was.util.CheckFileExist");



//this uses the system classloader and loads the ant class
Class c3 = ClassloaderTest.class.getClassLoader().loadClass("org.apache.tools.ant.BuildEvent");
//same as above, but through the URLClassloader. It throws a ClassNotFoundException for the ant class as expected
c3 = classLoader.loadClass("org.apache.tools.ant.BuildEvent");

//the only thing I found weird is that if you try to load a "standard" java class via the URLClassloader it returns the class
Class c2 = classLoader.loadClass("java.lang.String");

detlev_beutner
Active Contributor
0 Kudos

Hi Dagfinn (and Walter),

I came in here to give some Christmas presents

OK, Dagfinn's solution seems to be quite well working for Walter's needs. Some points to him!

So, if we are that deep in technical discussion, I would like to round off this one:

All this stuff on the one hand is quite technical, on the other hand life gets much more easy if at least one understands the basics. Much more I also don't do. So for example I mixed up system and bootstrap classloader in my last post (sorry!). Nevertheless, I also wasn't aware of the possibility of passing null, which is totally different from passing nothing. Seems to be very, very helpful to keep this in mind, thanks Dagfinn!

For your question about loading java.lang.String, Dagfinn: <i>This</i> is done by the bootstrap classloader. It may be irritating that in your example


classLoader.getParent()

returns <i>null</i>, but the explanation comes here:

ClassLoader.getParent() APIDoc: "Returns the parent class loader for delegation. Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class loader's parent is the bootstrap class loader."

To cut a long story short, let's come to the Christmas presents

- http://www.javaworld.com/javaqa/2003-06/01-qa-0606-load_p.html

- http://www.javaworld.com/javaworld/jw-03-2000/jw-03-classload_p.html

- http://www.panix.com/~mito/articles/articles/classloader/j-classloader-ltr.pdf

I hesitated about the last source, because I have heard that there are different mistakes in it, on a glance I just saw one big one: "The new model is a delegation model, which means that if your ClassLoader can't find a class, it asks its parent ClassLoader to do it."

NO! The opposite is the case, as written in the first: "every classloader (except for the primordial classloader that bootstraps the entire JVM) has a single parent. When asked to load a class, every compliant classloader is expected to delegate loading to its parent first and attempt to define the class only if the parent fails."

This should be enough stuff for boring winter days...

Best regards

Detlev

Answers (0)