Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Gemini » Blueprint broken with alternate DocumentBuilderFactory provider
icon5.gif  Blueprint broken with alternate DocumentBuilderFactory provider [message #824492] Mon, 19 March 2012 14:37 Go to next message
Paul Duffin is currently offline Paul Duffin
Messages: 9
Registered: July 2009
Junior Member
I just tried converting a Declarative Services based module to Blueprint and came across the following error, where <BUNDLE> is the name of my bundle, removed to protect the innocent.

[2012-03-19 16:27:21.100] sync Event Dispatcher Thread <AG0000E> Application context creation failure for bundle '<BUNDLE>' version '....'. org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from OSGi resource[bundleentry://139.fwk6627600/OSGI-INF/blueprint/time-factory.xml|bnd.id=139|bnd.sym=<BUNDLE>]; nested exception is javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not found
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:412)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
	at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
	at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:170)
	at org.eclipse.gemini.blueprint.context.support.OsgiBundleXmlApplicationContext.loadBeanDefinitions(OsgiBundleXmlApplicationContext.java:140)
	at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
	at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:467)
	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.access$800(AbstractDelegatedExecutionApplicationContext.java:60)
	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext$3.run(AbstractDelegatedExecutionApplicationContext.java:242)
	at org.eclipse.gemini.blueprint.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.startRefresh(AbstractDelegatedExecutionApplicationContext.java:220)
	at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.stageOne(DependencyWaiterApplicationContextExecutor.java:224)
	at org.eclipse.gemini.blueprint.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor.refresh(DependencyWaiterApplicationContextExecutor.java:177)
	at org.eclipse.gemini.blueprint.context.support.AbstractDelegatedExecutionApplicationContext.refresh(AbstractDelegatedExecutionApplicationContext.java:157)
	at org.eclipse.gemini.blueprint.extender.internal.activator.LifecycleManager$1.run(LifecycleManager.java:222)
	at java.lang.Thread.run(Thread.java:662)
Caused by: javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not found
	at javax.xml.parsers.DocumentBuilderFactory.newInstance(DocumentBuilderFactory.java:129)
	at org.springframework.beans.factory.xml.DefaultDocumentLoader.createDocumentBuilderFactory(DefaultDocumentLoader.java:89)
	at org.eclipse.gemini.blueprint.context.support.BlueprintDocumentLoader.createDocumentBuilderFactory(BlueprintDocumentLoader.java:42)
	at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:70)
	at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:388)
	... 18 common frames omitted


I believe that it behaves like that because of the following:

* The Gemini Blueprint Extender calls the Spring Framework code to load the beans setting the Thread ContextClassLoader to provide access to resources from the Blueprint Bundle, i.e. the one containing the blueprint XML file being processed. The intent behind that is to make sure that the Spring Framework can access all the classes in the Blueprint Bundle which is correct according to the blueprint specification.

* The XmlBeanDefinitionReader.doLoadBeanDefinitions() class tries to load the DocumentBuilderFactory class using the DocumentBuilderFactory.newInstance() method. That uses the Thread ContextClassLoader to load the service definition.

* I have installed a Xerces OSGi bundle in the user region. That contains a resource META-INF/services/javax.xml.parsers.DocumentBuilderFactory which contains the value "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl". The DocumentBuilderFactory.newInstance() method picks up that value because the Blueprint Bundle that contains the blueprint file imports some packages from that bundle; I believe that this is correct behaviour.

* The "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl" class is not found because the Blueprint Bundle does not import that package.

I could work around the issue by adding DynamicImport-Package: * but it is completely wrong that a bundle that does not make use of a DocumentBuilderFactory should have to import it just because an Extender has to use one. I could probably have made it less open and just used DynamicImport-Package: org.apache.xerces.jaxp but that is no better.

It seems to me that the fundamental problem here is the way that the Spring Beans code is accessing the DocumentBuilderFactory instance. In fact the OSGi Architecture page (cannot add a link as this is my first post, google for "OSGi Architecture") uses the DocumentBuilderFactory.newInstance() mechanism as an example of a bad way of doing that and explains that OSGi services are better. I realise that the code probably has to work in a non-OSGi environment as well but as it is a core part of something that is intended to work inside OSGi it should be OSGi aware in the way it gets access to the factory.

As I see it, and I do not really know Spring very well, the simplest solution is just to add an activator to the Spring Beans Bundle that will store a reference to the DocumentBuilderFactory service in a place that is accessible to the code that needs it. If it is not set then will work as now using DocumentBuilderFactory.newInstance() preserving existing behaviour outside OSGi, and using the service within OSGi.

I am happy to raise a bug for this but I just wanted to make sure that I wasn't doing something stupid first.
Re: Blueprint broken with alternate DocumentBuilderFactory provider [message #824933 is a reply to message #824492] Tue, 20 March 2012 04:58 Go to previous messageGo to next message
Glyn Normington is currently offline Glyn Normington
Messages: 1222
Registered: July 2009
Senior Member
This kind of thing cropped up in Virgo. See this thread for a possible solution.
Re: Blueprint broken with alternate DocumentBuilderFactory provider [message #825016 is a reply to message #824933] Tue, 20 March 2012 07:03 Go to previous messageGo to next message
Paul Duffin is currently offline Paul Duffin
Messages: 9
Registered: July 2009
Junior Member
Glyn, thanks for the prompt reply.

I did actually find that issue when I was looking for a solution/explanation of this and while I think that it is the same problem the answer was a work around rather than a real and general solution.

After I raised this topic I investigated some more and think that it is possible for this to be addressed by Gemini Blueprint code without any changes to Spring.

The Gemini Blueprint code could supply its own implementation of DocumentLoader. Ideally, it would be able to extend Spring's DefaultDocumentLoader to replace the code that obtains the instance and reuse the code that initializes the DocumentBuilderFactory instance. Unfortunately both pieces of functionality are combined within its createDocumentBuilderFactory() method.

That means that Gemini Blueprint code would have to duplicate the initialization functionality of DefaultDocumentLoader but instead of using DocumentBuilderFactory.newInstance() it would have to obtain an instance from OSGi service registry.

Do you consider this problem a bug? I am quite happy to help where I can.

The reason that this usually works is that the default parser is com.sun.... which is always loaded from the boot loader.
Re: Blueprint broken with alternate DocumentBuilderFactory provider [message #825061 is a reply to message #825016] Tue, 20 March 2012 08:12 Go to previous message
Glyn Normington is currently offline Glyn Normington
Messages: 1222
Registered: July 2009
Senior Member
It's certainly a limitation, so feel free to raise an enhancement bugzilla and develop a patch if you would like to. Note that I'm not sure what the plans are for future releases of Gemini Blueprint as I'm not a Blueprint committer and am only slowly coming up to speed.
Previous Topic:Scoped/Prototype beans via service registry?
Next Topic:blueprint inside eclipse rcp
Goto Forum:
  


Current Time: Thu Jul 31 16:00:49 EDT 2014

Powered by FUDForum. Page generated in 0.03826 seconds