Skip to content

Improve core container exception meta-data [SPR-13968] #18540

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

Closed
spring-projects-issues opened this issue Feb 22, 2016 · 7 comments
Closed

Improve core container exception meta-data [SPR-13968] #18540

spring-projects-issues opened this issue Feb 22, 2016 · 7 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Feb 22, 2016

Stéphane Nicoll opened SPR-13968 and commented

Andy Wilkinson submitted two PRs to improve the meta-data of the core container exception. We should review those and further improve it if necessary. The PRs are #969 and #965


Affects: 4.2.4

Issue Links:

Referenced from: commits b6f6949, b6dd8a9

@spring-projects-issues
Copy link
Collaborator Author

Andy Wilkinson commented

I have another change that I'd like to see. I haven't submitted a pull request for it, as I'm really not sure how to go about it.

I’d like NoUniqueBeanDefinitionException to provide access to the definitions of the beans rather than only their names. I thought about doing it in Boot and using the names to look up the definitions in the bean factory, but I have no way of knowing what sort of search was done when trying to find the beans (whether or not ancestor factories were consulted). Looking at doing it in the core, adding the definitions to the exception isn’t straightforward. I can only get the definition from a DefaultListableBeanFactory and in a lot of places its a ListableBeanFactory that’s passed around. I could do an instanceof and cast, but then the behaviour will be inconsistent if there’s a custom bean factory involved.

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Andy Wilkinson, I'm trying to address the intent of your two pull requests in a slightly different way... rolling it into UnsatisfiedDependencyException itself or maybe one custom variant of it, but ideally not separate ones for field/method/constructor. I might change my mind still, but anyway, just a note that I'm on it :-)

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Current outcome: a new UnsatisfiedDependencyException constructor taking an InjectionPoint descriptor, used by ConstructorResolver as well as AutowiredAnnotationBeanPostProcessor, delivering a consistent exception surface for all autowired injection points now, with no unnecessary wrapping anymore. And of course, allowing for programmatic access to the field/method/constructor through the new getInjectionPoint() method on UnsatisfiedDependencyException.

InjectionPoint is a base class of our existing DependencyDescriptor, factoring out the core artifact references. We don't make use of that class hierarchy relationship yet (since we always create our own InjectionPoint instances for exception purposes, just reusing MethodParameter handles), but technically, an UnsatisfiedDependencyException could be created directly from a DependencyDescriptor now.

@spring-projects-issues
Copy link
Collaborator Author

Andy Wilkinson commented

Juergen Hoeller, this looks great. Thank you.

Did you have a chance to consider my comment above, about provided access to the definitions of the beans involved in a NoUniqueBeanDefinitionException. Assuming you think that's something that could and should be made possible, shall I open an issue?

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Andy Wilkinson, I'm not keen on including entire BeanDefinition objects there since they contain quite a bit of weight... and also come from the beans.factory.config subpackage, so can't be easily linked into a {{beans.factory}-defined exception.

As for resolving such bean names yourself, note that ConfigurableBeanFactory.getMergedBeanDefinition actually traverses the hierarchy for you if necessary. Since beans in a child factory always override same-named beans in an ancestor, bean names can be reliably resolved that way. The only special case you should take into account is that there might not be a backing bean definition at all, e.g. in case of a manually registered singleton instance. So if getMergedBeanDefinition throws a NoSuchBeanDefinitionException, either just ignore it or try to reduce the introspection to BeanFactory.getType (and the like) which is nevertheless going to work.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

Andy Wilkinson commented

Thanks, Juergen Hoeller. I've prototyped something based on getMergedBeanDefinition and it seems to work nicely. The only small fly in the ointment is where I retrieve the bean names from the NoUniqueBeanDefinitionException as there's no getter for them. Would it be possible to add one so that I can avoid doing this:

private String[] extractBeanNames(NoUniqueBeanDefinitionException cause) {
	if (cause.getMessage().indexOf("but found") > -1) {
		return StringUtils.commaDelimitedListToStringArray(cause.getMessage()
				.substring(cause.getMessage().lastIndexOf(":") + 1).trim());
	}
	return null;
}

@spring-projects-issues
Copy link
Collaborator Author

Juergen Hoeller commented

Ah, good catch. I'll add a corresponding getBeanNamesFound accessor for 4.3 then.

Juergen

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) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants