|
From: Solomon D. <sd...@gm...> - 2013-04-18 02:33:27
|
Thank you for the careful analysis. I'll see if I can work around this
issue using other approaches relating to the Spring lifecycle. I fixed a
similar issue a while back with @Providers, and might be able to use the
same approach for ResteasyRegistration.
I hope to check in something tomorrow. Since this is a nuanced issue, I
think that this change would benefit from field testing. Would you feel
comfortable with being beta testers for this change?
-Solomon
On Wed, Apr 17, 2013 at 7:37 PM, Gendler, Samuel <
Sam...@we...> wrote:
> So it proved to be even more subtle than just the existence of a factory
> bean. It has to be a factory bean that doesn’t declare the type of objects
> it will create – which is probably limited only to things like
> JndiObjectFactoryBean. The FactoryBean interface declares a method called
> getObjectType() which is explicitly supposed to return null if the type of
> the object is not known in advance. The following is from the javadoc for
> FactoryBean:****
>
> ** **
>
> Returns:****
>
> the type of object that this FactoryBean creates, or null if not known at
> the time of the call****
>
> ** **
>
> When I created a factory bean that specifies a type in getObjectType(),
> the properties were not initialized during the SpringBeanProcessor’s call
> to getBeansOfType(). When I created a factory bean that returns null, my
> properties get initialized with the values before property placeholder has
> done its thing because it actually asks the factory for the bean in order
> to determine the type, so it must initialize it first. I’m not quite sure
> what the fix to this would be, since the logic of what is going on in
> SpringBeanProcessor isn’t entirely clear to me, but it does appear to be a
> bug on the resteasy side of things. Somehow, this code needs to execute
> after property placeholder replacement (this seems to be the case in
> resteast 2.2.3.GA, which still contains calls to getBeansOfType(), but
> doesn’t trigger this bug, so something is happening to change the order of
> events).****
>
> ** **
>
> *From:* Gendler, Samuel
> *Sent:* Wednesday, April 17, 2013 4:05 PM
> *To:* 'res...@li...'
> *Cc:* 'res...@li...'
> *Subject:* RE: spring bean processor bug****
>
> ** **
>
> One further piece of info – the javadoc for getBeansOfType() says that
> factories will be initialized in order to check the type of returned
> objects. My jndiTemplate is referenced by a bean created via a factory,
> and I suspect that this is why it is causing the jndiTemplate to be
> initialized while beans that have identical properties but are not used by
> factories are not initialized until much later and only after property
> placeholder replacement has occurred. I haven’t actually verified this
> hypothesis, but it seems likely. My factory beans are declared as follows:
> ****
>
> ** **
>
> <bean id="sonicJmsTradeConnectionFactory"
> class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
> ****
>
> <property name="targetConnectionFactory">****
>
> <bean class="org.springframework.jndi.JndiObjectFactoryBean">****
>
> <property name="jndiTemplate" ref="jndiTemplate" />****
>
> <property name="jndiName">****
>
> <value>${jndi.ConnectionFactory}</value>****
>
> </property>****
>
> </bean>****
>
> </property>****
>
> <property name="username">****
>
> <value>${jndi.user}</value>****
>
> </property>****
>
> <property name="password">****
>
> <value>${jndi.password}</value>****
>
> </property>****
>
> </bean>****
>
> ** **
>
> <bean id="destination"
> class="org.springframework.jndi.JndiObjectFactoryBean">****
>
> <property name="jndiTemplate" ref="jndiTemplate" />****
>
> <property name="jndiName">****
>
> <value>${jndi.TopicName}</value>****
>
> </property>****
>
> </bean>****
>
> ** **
>
> My guess is that it is actually incorrect to utilize the getBeansOfType()
> methods in an application context which is not yet completely initialized.
> At the same time, I don’t really understand why setting the order to
> LOWEST_PRECEDENCE doesn’t fix the problem unless something internal to
> spring is ignoring the suggested ordering.****
>
> ** **
>
> *From:* Gendler, Samuel [mailto:Sam...@we...<Sam...@we...>]
>
> *Sent:* Wednesday, April 17, 2013 3:36 PM
> *To:* 'res...@li...'
> *Cc:* 'res...@li...'
> *Subject:* [Resteasy-developers] spring bean processor bug****
>
> ** **
>
> I recently upgraded a project from 2.2.3.GA to 2.3.6.FINAL and
> encountered a bug that appears to originate in the SpringBeanProcessor and
> which breaks property placeholder variable replacement in certain spring
> beans.****
>
> ** **
>
> I haven’t completely unwound the bug to the root cause, but I’ve gotten
> close enough to be confident that someone with more resteasy knowledge can
> likely address it much more quickly than I can.****
>
> ** **
>
> First, the symptoms:****
>
> ** **
>
> I have a bean of class org.springframework.jndi.JndiTemplate declared as
> follows:****
>
> ** **
>
> <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">**
> **
>
> <property name="environment">****
>
> <props>****
>
> <prop
> key="java.naming.factory.initial">com.sonicsw.jndi.mfcontext.MFContextFactory</prop>
> ****
>
> <prop key="java.naming.provider.url">${jndi.url}</prop>****
>
> <prop key="java.naming.security.principal">${jndi.user}</prop>****
>
> <prop
> key="java.naming.security.credentials">${jndi.password}</prop>****
>
> <prop key="com.sonicsw.jndi.mfcontext.domain">${jndi.domain}</prop>
> ****
>
> <prop key="clientId">${jndi.clientId}</prop> ****
>
> <prop key="subscriptionDurable">true</prop>****
>
> <prop
> key="durableSubscriptionName">${jndi.durableSubscriptionName}</prop>
> ****
>
> <prop key="timeToLive">${jndi.timeToLive}</prop>****
>
> <prop
> key="com.sonicsw.jndi.mfcontext.idleTimeout">${jndi.timeout}</prop>****
>
> </props>****
>
> </property>****
>
> </bean>****
>
> ** **
>
> I have a property placeholder that is most definitely initialized with
> values for all of those properties. I can set the same values in a test
> object and see that they are correctly replaced. However, for reasons that
> I’ll get into in a moment, the jndiTemplate properties are NOT replaced and
> it receives the raw ${…} strings instead. Needless to say, this breaks my
> project. Switching back to 2.2.3.GA definitely fixes it without making
> any other changes.****
>
> ** **
>
> What I’ve discovered so far about the cause:****
>
> ** **
>
> In SpringBeanProcessor.postProcessBeanFactory(), a method called
> findResteasyRegistrations() is called. That method, in turn, calls the
> following:****
>
> ** **
>
> beanFactory.getBeansOfType(ResteasyRegistration.class);****
>
> ** **
>
> That method call causes some beans (but not all beans) to be instantiated,
> and any beans that are instantiated at that point do not have property
> placeholder values replaced in them, because the property placeholder
> processor has (apparently) not yet executed. What I haven’t figured out is
> why my jndiTemplate bean is impacted by this, while another bean that I
> created simply to test the creation of properties inside of a bean
> definition is not. It is apparently skipped over by the
> getBeansOfType(ResteasyRegistration.class) and property replacement happens
> correctly in that case.****
>
> ** **
>
> Initially, I suspected that this was a problem with post processor
> ordering. This was somewhat vexing as the SpringBeanProcessor does
> implement the PriorityOrdered interface, but exposes no mechanism for
> modifying the order value. I created my own version of
> SpringContextLoaderListener which forgoes the use of
> SpringContextLoaderSupport and performs the same work, but also calls
> setOrder(x) on the SpringBeanProcessor before adding it to the
> postprocessors and application listeners. However, that didn’t seem to
> have any impact, no matter in which relative order I placed the property
> placeholder and the spring bean processor.****
>
> ** **
>
> For one final data point, if I don’t use a property placeholder, but
> instead reference a properties object via Spring-EL in the XML, then the
> values are correctly replaced, because the spring-el is evaluated when the
> xml is parsed (I assume), while property placeholders are definitely
> evaluated lazily, long after the bean definitions are created by the xml
> parsing process.****
>
> ** **
>
> <util:properties id="jmsProperties"
> location="file:${catalina.base}/conf/jms.properties"/>****
>
> ****
>
> <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">**
> **
>
> <property name="environment">****
>
> <props>****
>
> <prop
> key="java.naming.factory.initial">com.sonicsw.jndi.mfcontext.MFContextFactory
> ****
>
> </prop>****
>
> <prop
> key="java.naming.provider.url">#{jmsProperties['jndi.url']}</prop>****
>
> <prop
> key="java.naming.security.principal">#{jmsProperties['jndi.user']}</prop>*
> ***
>
> <prop
> key="java.naming.security.credentials">#{jmsProperties['jndi.password']}</prop>
> ****
>
> <prop
> key="com.sonicsw.jndi.mfcontext.domain">#{jmsProperties['jndi.domain']}</prop>
> ****
>
> <prop
> key="clientId">#{jmsProperties['jndi.clientId']}</prop> ****
>
> <prop key="subscriptionDurable">true</prop>****
>
> <prop
> key="durableSubscriptionName">#{jmsProperties['jndi.durableSubscriptionName']}</prop>
> ****
>
> <prop key="timeToLive">#{jmsProperties['jndi.timeToLive']}</prop>*
> ***
>
> <prop
> key="com.sonicsw.jndi.mfcontext.idleTimeout">#{jmsProperties['jndi.timeout']}</prop>
> ****
>
> </props>****
>
> </property>****
>
> </bean>****
>
> ** **
>
> This works, but is a kludge. I’d much prefer to have
> property-placeholding actually functional, especially since it is
> apparently impossible to predict which beans will fail to have properties
> replaced. Looking at the sourec code to jndiTemplate, I can see no obvious
> reason why it is treated differently than my own test bean. Both have no
> annotations and both receive a java.util.Properties object as a property.
> The behavior is consistent no matter what order they appear in my context
> xml file.****
>
> ** **
>
> I’ve attached my replacement SpringContextLoaderListener just for
> reference, in case someone else wants to modify the ordering of the
> placeholders while testing or fixing this. The relevant web.xml entries
> are below:****
>
> ** **
>
> <context-param>****
>
> <param-name>resteasy.postprocessor.order</param-name>****
>
> <param-value>0</param-value>****
>
> </context-param>****
>
> ** **
>
> <listener>****
>
> <listener-class>****
>
>
> org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
> ****
>
> </listener>****
>
> ** **
>
> <listener>****
>
> <!--
> listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class-->
> ****
>
> <listener-class>****
>
> com.westernasset.compliance.util.SpringContextLoaderListener****
>
> </listener-class>****
>
> </listener>****
>
> ** **
>
> **********************************************************************
> E-mail sent through the Internet is not secure. Western Asset therefore
> recommends that you do not send any confidential or sensitive information
> to us via electronic mail, including social security numbers, account
> numbers, or personal identification numbers. Delivery, and or timely
> delivery of Internet mail is not guaranteed. Western Asset therefore
> recommends that you do not send time sensitive or action-oriented messages
> to us via electronic mail.
> ********************************************************************** ***
> *
>
>
> ------------------------------------------------------------------------------
> Precog is a next-generation analytics platform capable of advanced
> analytics on semi-structured data. The platform includes APIs for building
> apps and a phenomenal toolset for data science. Developers can use
> our toolset for easy data analysis & visualization. Get a free account!
> http://www2.precog.com/precogplatform/slashdotnewsletter
> _______________________________________________
> Resteasy-developers mailing list
> Res...@li...
> https://lists.sourceforge.net/lists/listinfo/resteasy-developers
>
>
|