Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Virgo » Bean factory post processors
Bean factory post processors [message #725378] Wed, 14 September 2011 15:56 Go to next message
Tin N/A is currently offline Tin N/AFriend
Messages: 46
Registered: December 2010
Member
Hi,

well, after extensive googling, I thought I'd ask here. So, the subject contains the key to the question, and the question is simple: are Spring's standard bean factory post processors supposed to work?
I'm asking because implementing a BeanDefinitionRegistryPostProcessor interface,
both callbacks (postProcessBeanFactory and postProcessBeanDefinitionRegistry) are
NOT called even though the constructor of the class itself is.

I found there exists the OsgiBeanFactoryPostProcessor in SpringDM - is maybe that the right way to use post processing functionality?

And a related question - I'm actually using post processors to define beans that are configured externally. The idea is to have one bundle exposing multiple services, with those services being enabled by external configuration settings. The context elements (beans and OSGi imports/exports) for each service are defined in separate context config files. The only bean automatically started is a post processor that reads the external configuration, loads (into XmlBeanFactory) the context config file for each of the services it needs enabled. Can you see any problems with this approach? Are bean definitions (including OSGi imports/exports) going to be interpreted correctly when copied to bundle's application context (since they are loaded programatically by XmlBeanFactory)?

Thanks in advance!
Tin
Re: Bean factory post processors [message #725520 is a reply to message #725378] Thu, 15 September 2011 04:22 Go to previous messageGo to next message
Dmitry Sklyut is currently offline Dmitry SklyutFriend
Messages: 278
Registered: January 2010
Senior Member
Maybe a quick example will help here. Can you throw together a set of test bundles so we can eye ball them?

Thanks
Dmitry
Re: Bean factory post processors [message #725529 is a reply to message #725520] Thu, 15 September 2011 05:59 Go to previous messageGo to next message
Tin N/A is currently offline Tin N/AFriend
Messages: 46
Registered: December 2010
Member

Nothing easier Very Happy

It's just one bundle, attached to this post (it's an Eclipse STS project, but the bundle itself you can find in the target/ subdirectory).
So the aim is, as described in the first post, to be able to initialize only the selected services out of all the services that the bundle can provide. The logic for that is implemented in the test.bfpp.ServiceActivatingPostProcessor class. Each of the services has its own context file which the aforementioned class then loads and copies their bean definitions into current registry.

I actually lied in my first post - the bean factory post processor hook does get called, but the registry hook does not, and I want that one so that beans are defined early enough to be able to benefit from property placeholder post processing.

I'm testing this on Virgo 2.1, but with Spring updated to 3.0.5, so the registry hook should work (it was added in 3.0.1).

Thanks in advance, and any suggestions about a different approach to achieve the same goal described above are much appreciated!
Re: Bean factory post processors [message #725706 is a reply to message #725529] Thu, 15 September 2011 14:57 Go to previous messageGo to next message
Dmitry Sklyut is currently offline Dmitry SklyutFriend
Messages: 278
Registered: January 2010
Senior Member
I have one answer for you and an idea on the configuration.

Answer to "Why is spring 3.x method not invoked"?
Because spring-osgi code is coded against spring 2.5.x and also overrides AbstractApplicationContext#invokeBeanFactoryPostProcessors. This override bypasses logic to call into registry post processor.

Some ideas now:

Take a look at ManagedServiceFactory interface in OSGi spec and potentially in spring-osgi docs.
You can create a Factory that is able to accept configuration objects or Map and make a decision on service publication.

With ManagedServiceFactory you kind of get the conditional behavior with externally loaded config files (through ConfigurationAdmin and in virgo with .properties i.e. configuration type artifacts) and also able to react to configuration.


Hope this helps.

Regards,
Dmitry
Re: Bean factory post processors [message #725787 is a reply to message #725706] Thu, 15 September 2011 19:00 Go to previous messageGo to next message
Tin N/A is currently offline Tin N/AFriend
Messages: 46
Registered: December 2010
Member
Thanks Dmitry!

Well, I read up on ManagedServiceFactory and it does look like it's designed with use cases in mind that are similar to mine. The thing is - Spring just makes it that bit more elegant to do using post processors, so it's worth pursuing doing it the "Spring way".

Is there a need to raise an issue/wish item in Virgo tracker to implement support for registry post processor, or is this already planned, or maybe can't be done because of Spring dependency (not sure how Spring framework usage is regulated between Eclipse and SpringSouce/VMWare).

And a related question - when you move the code in my example post processor class to the postProcessBeanFactory method (which does get called), a problem surfaces with Xerces apparently not being able to parse the "osgi" XML elements. It pauses for a while when starting the bean, as if it wanted to load namespace schemas from the net (i.e. from the HTTP URL defined in schema location), and then it dies with an error about not being able to find the "osgi:service" definition. Any ideas why that is - it seems like the XmlBeanFactory (the same happens if I only use XmlBeanDefinitionReader) object created in that method does not have access to the namespace schemas included with Spring bundles, but rather tries to load them directly from their URL locations?

[Updated on: Thu, 15 September 2011 19:02]

Report message to a moderator

Re: Bean factory post processors [message #725796 is a reply to message #725787] Thu, 15 September 2011 19:31 Go to previous messageGo to next message
Glyn Normington is currently offline Glyn NormingtonFriend
Messages: 1222
Registered: July 2009
Senior Member
canobix wrote on Thu, 15 September 2011 20:00
(not sure how Spring framework usage is regulated between Eclipse and SpringSouce/VMWare).

There's no regulation except that Spring dependencies that we build into Virgo need to go through the Eclipse IP process. The constraints are purely technical!
Re: Bean factory post processors [message #725801 is a reply to message #725787] Thu, 15 September 2011 19:45 Go to previous messageGo to next message
Dmitry Sklyut is currently offline Dmitry SklyutFriend
Messages: 278
Registered: January 2010
Senior Member
please do submit an issue in bugzilla to cover this. It is doable with springdm 2.x but I have to check on the plans to upgrade to gemini-blueprint.

on that related question - this is a peculiar situation of osgi classloading Smile
SpringDM supports spring namespace resolution. But because you are creating a bean factory by hand, you are loosing out on that support. If you want gory details please let me know.


Re: Bean factory post processors [message #725884 is a reply to message #725801] Fri, 16 September 2011 05:09 Go to previous messageGo to next message
Tin N/A is currently offline Tin N/AFriend
Messages: 46
Registered: December 2010
Member
Thanks Glyn and Dmitry, since there seem to be no legal or technical obstacles, I've submitted an enhancement request in the tracker.

Dmitry, I'll take a look then in the SpringDM sources to try to understand how it handles namespace resolutions and either figure out how to obtain the "resolution-enhanced" bean definition reader, or replicate the functionality that Spring DM provides (I've already tried blindly experimenting with setting bean definition reader's classloader but it doesn't seem to have any effect). Just please let me know if you think I'm on the wrong track trying to investigate in that direction Very Happy
Re: Bean factory post processors [message #726043 is a reply to message #725884] Fri, 16 September 2011 13:16 Go to previous messageGo to next message
Dmitry Sklyut is currently offline Dmitry SklyutFriend
Messages: 278
Registered: January 2010
Senior Member
You might find this interesting: http://gnodet.blogspot.com/2010/03/spring-dm-aries-blueprint-and-custom.html
Re: Bean factory post processors [message #726659 is a reply to message #726043] Mon, 19 September 2011 07:44 Go to previous messageGo to next message
Tin N/A is currently offline Tin N/AFriend
Messages: 46
Registered: December 2010
Member
It was an interesting read, thanks, although I'm not sure who won in that comments exchange Very Happy It's good to know, even though SpringSource's focus shifted away from OSGi, there is a wider group of people still working on getting it ready for more complex uses.

Meanwhile, I discovered a way to programatically add bean and OSGi service definitions with current level of post processor support, and while it might not be optimal it does work:

1. Implement a BeanFactoryPostProcessor and a BundleContextAware in the same class
2. In the postProcessBeanFactory method do this:
a) create a new OsgiBundleXmlApplicationContext
b) call setBundleContext on the object from a)
c) call setConfigLocations on the object from a), with location of the XML file(s) describing beans and services you want to instance
d) call refresh on the object from a)
e) access getBeanFactory on the object from a) to get all bean definitions and use registerBeanDefinition to register it in the current bean factory

There might be a simpler way to do it that maybe doesn't require creating a whole application context, but at least this is a good start...

[Updated on: Mon, 19 September 2011 07:45]

Report message to a moderator

Re: Bean factory post processors [message #727291 is a reply to message #726659] Tue, 20 September 2011 19:42 Go to previous messageGo to next message
Dmitry Sklyut is currently offline Dmitry SklyutFriend
Messages: 278
Registered: January 2010
Senior Member
That is an interesting approach Smile

The one I had in mind included a fragment bundle and a few customized classes to from spring-dm to achieve the same. I will post the code in a bit for anyone who is interested.
Re: Bean factory post processors [message #729230 is a reply to message #727291] Sun, 25 September 2011 14:18 Go to previous messageGo to next message
Tin N/A is currently offline Tin N/AFriend
Messages: 46
Registered: December 2010
Member
Please do. My idea was to try and keep everything in one bundle. Fragments, I must admit, didn't even come to mind, so it will be interesting to see any alternatives.
Re: Bean factory post processors [message #804621 is a reply to message #729230] Wed, 22 February 2012 20:41 Go to previous messageGo to next message
Kay Huber is currently offline Kay HuberFriend
Messages: 36
Registered: July 2009
Member
I've stumbled over your post about BeanDefinitionRegistryPostProcessor not being available in Spring DM / Eclipse gemini blueprint and found your bugzilla entry at https://bugs.eclipse.org/bugs/show_bug.cgi?id=357903
I'm having this problem using eclipse gemini only (without virgo). Maybe your issue should be moved to gemini bugzilla...
Re: Bean factory post processors [message #900521 is a reply to message #726659] Tue, 07 August 2012 11:37 Go to previous messageGo to next message
Mektoub TheBearKiller is currently offline Mektoub TheBearKillerFriend
Messages: 1
Registered: August 2012
Junior Member
Hi,

I'm trying to do the same thing and I tried your proposed approach but I'm facing a problem : my beans are defined with properties, example :
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="${jms.brokerURL}" />
</bean>

And it seems there are not resolved during registration.
FuseESB:karaf@root> update 228Exception in thread "SpringOsgiExtenderThread-51" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmsConnectionFactory' defined in URL [bundle://227.0:1/META-INF/spring/socle-jms.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'brokerURL' threw exception; nested exception is java.lang.IllegalArgumentException: Invalid broker URI: ${jms.brokerURL}
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1363)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1085)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:516)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:69)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:355)
at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'brokerURL' threw exception; nested exception is java.lang.IllegalArgumentException: Invalid broker URI: ${jms.brokerURL}
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:102)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
... 15 more

My code :

URL resourceUrl = new Url("bundle://227.0/META-INF/spring/socle-jms.xml");
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(registry);
Resource resource = new UrlResource(resourceUrl);
beanDefinitionReader.loadBeanDefinitions(resource);

Any clue ?
Re: Bean factory post processors [message #900533 is a reply to message #900521] Tue, 07 August 2012 12:22 Go to previous message
Tin N/A is currently offline Tin N/AFriend
Messages: 46
Registered: December 2010
Member
I'd say this is because no propertyplaceholderconfigurers are instanced and applied when you just read bean definitions. Here's a complete method that works for me, with some comments included (note that sample-setup.xml can and should contain property placeholder configurer declaration for your case to work):


@Override
	public void setBundleContext ( BundleContext bc )
	{
		this.bc = bc;
	}

@Override
	public void postProcessBeanFactory ( ConfigurableListableBeanFactory factory )
			throws BeansException
	{
		DefaultListableBeanFactory dlbf = (DefaultListableBeanFactory) factory;

		// Setup the "donor" application context that will be used to load necessary
		// bean definitions
		OsgiBundleXmlApplicationContext ctx = new OsgiBundleXmlApplicationContext ( );

  // bc obtained above - by implementing BundleContextAware.setBundleContext
		ctx.setBundleContext ( bc );

		// Initialize bean definition locations in the "donor" context
		ctx.setConfigLocations ( new String [ ] { "META-INF/sample-setup.xml" } );

		// Load bean definitions
		ctx.refresh ( );

		// Copy bean definitions from "donor" to current context
		for ( String bean : ctx.getBeanFactory ( ).getBeanDefinitionNames ( ) )
		{
   // Register bean definitions in current application context
			dlbf.registerBeanDefinition ( bean, ctx.getBeanFactory ( ).getBeanDefinition ( bean ) );
		}
	}


So, your sample-setup.xml could look like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:osgi="http://www.springframework.org/schema/osgi"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">

	<context:property-placeholder location="file:/etc/sample.conf"/>

 <bean id="someString" class="java.lang.String" factory-method="valueOf">
   <constructor-arg value="${sample.value}"/>
 </bean>
</beans>

Previous Topic:Virgo Server for Apache Tomcat - Production Usage
Next Topic:Clean doesn't work as expected
Goto Forum:
  


Current Time: Mon Dec 22 12:05:05 GMT 2014

Powered by FUDForum. Page generated in 0.08915 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software