Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get real ID of the application context in ApplicationContextAware.setApplicationContext() [SPR-8816] #13458

Closed
spring-projects-issues opened this issue Nov 3, 2011 · 3 comments
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

Leo Liang opened SPR-8816 and commented

I create a bean to implement the ApplicationContextAware interface and print out the current context id. But the id isn't the one I specify in xml, it's a generated one like "org.springframework.context.support.ClassPathXmlApplicationContext@15e9756". At the same place I print the id of the parent context, it's the real one.

I guess that reason is: at the time when ApplicationContextAware is invoked, id isn't set yet. Can it be changed so that real context id can be retrieve in ApplicationContextAware?

== Java code:

public class ApplicationContextDumper implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
String appContextInfo = String.format("ApplicationContext %s", context.getId());
ApplicationContext parent = context.getParent();
if (parent != null) {
appContextInfo += String.format(" -> %s", parent.getId());
}
System.out.println(appContextInfo);
}
}

public class TestMain {
public static void main(String[] args) {
String[] paths = { "classpath:**/beanRefContext.xml" };
new ClassPathXmlApplicationContext(paths);
}
}

== beanRefContext.xml:
...
<bean id="parentBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>classpath:/parentContext.xml</value>
</list>
</constructor-arg>
</bean>
<bean id="myBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>classpath:
/applicationContext.xml</value>
</list>
</constructor-arg>
<constructor-arg>
<ref bean="parentBeanFactory" />
</constructor-arg>
</bean>
...

== applicationContext.xml:
...
<bean class="springtest.ApplicationContextDumper" />
...

== Expected output:

ApplicationContext myBeanFactory -> parentBeanFactory

== Actual output:

ApplicationContext org.springframework.context.support.ClassPathXmlApplicationContext@15e9756 -> parentBeanFactory


Affects: 3.0.6

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Hi Leo,

Thanks for the report. I've verified the behavior as you've described it here, so indeed the problem is genuine.

However, a few factors lead me to resolve this as "won't fix".

  1. the use case here is rather unlikely to occur for other users
  2. there is a reasonable alternative / workaround approach
  3. making the changes necessary to accommodate this use case would almost certainly have unintended side effects worse than the problem it is solving

I'll go into detail on each of these points below, but first an explanation of the problem:

First, it's important to understand that the way the ApplicationContext's setId method is called is through the BeanNameAware callback. When an ApplicationContext is declared as a Spring bean, it gets its setBeanName method invoked, and uses the bean name to call setId(String).

So, the context itself is a bean that needs to be initialized, including having its \*Aware callbacks invoked. At the same time, the context contains bean definitions that themselves have \*Aware callbacks to be invoked. The way that the logic works today, the context's BeanNameAware callback gets invoked after the ApplicationContextAware callback of the bean within that context gets invoked.

This means that the context id will eventually get set to the bean name, just not in time for immediate interrogation within the ApplicationContextAware component upon invocation of the setApplicationContext method.

Regarding point #1 above: One must being declaring application context hierarchies as spring beans AND have an ApplicationContextAware component within one of those contexts AND need to interrogate the context id immediately. This is almost certainly not a common scenario.

Regarding point #2 above: There are two possible alternative approaches here. The first is to simply defer the interrogation of the context id. As mentioned above, the id will in fact be set to the bean name eventually. So, if reasonable for the purposes of your application, you could just defer interrogation of the context id. The second approach is not to use ApplicationContextAware, but rather implement ApplicationEventListener instead and react to the ContextRefreshed event when it is raised. By this time, the context id is guaranteed to have been set.

Regarding point #3 above: I have not fully analyzed what the effect would be of invoking the BeanNameAware callback earlier in the lifecycle, but it doesn't make conceptual sense, and will almost certainly violate previous assumptions and thus create subtle backward compat problems, if not outright breakages of functionality.

I hope this analysis helps, and that one of the alternative approaches can work for you.

Regards,

Chris

@spring-projects-issues
Copy link
Collaborator Author

Leo Liang commented

Hi Chris,

Thank you for your detail reply.

I have tried the second alternative approach as you advised, implement ApplicationEventListener and react to the ContextRefreshed event, but the context id isn't set as well at the time when the event is raised.

My purpose is to dump information of all beans and their relationship into log file when application context is loaded. Maybe there is other way to get these information?

Regards,
Leo

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Leo,

I am a bit surprised to hear that the ID isn't available on ContextRefreshed. For the reasons listed above, this is still not probably going to be a terribly high priority for us, however -- if you would be willing to create a very simple reproduction of this issue by following the instructions here https://github.com/SpringSource/spring-framework-issues#readme, I will take a further look into it.

If you do go ahead with this, please click 'reopen' on this issue and paste the link to the pull request.

Thanks,

Chris

@spring-projects-issues spring-projects-issues added status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement in: core Issues in core modules (aop, beans, core, context, expression) labels Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

1 participant