stormpath-sdk-java icon indicating copy to clipboard operation
stormpath-sdk-java copied to clipboard

Auto-configuration should have a dedicated exception type and failure analyzer for known scenario

Open snicoll opened this issue 8 years ago • 1 comments

I am creating an empty Spring Boot app with the default stormpath starter. When I run the application, I get the following:

2017-01-31 08:26:30.943 ERROR 13032 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:137) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:536) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at com.example.DemoApplication.main(DemoApplication.java:10) [classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_112]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_112]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_112]
	at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:527) [spring-boot-maven-plugin-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_112]
Caused by: org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
	at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.initialize(TomcatEmbeddedServletContainer.java:117) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.<init>(TomcatEmbeddedServletContainer.java:84) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getTomcatEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:537) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory.getEmbeddedServletContainer(TomcatEmbeddedServletContainerFactory.java:179) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:164) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:134) ~[spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
	... 14 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.stormpath.spring.boot.autoconfigure.StormpathWebMvcAutoConfiguration': Unsatisfied dependency expressed through field 'client'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stormpathClient' defined in class path resource [com/stormpath/spring/boot/autoconfigure/StormpathAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.stormpath.sdk.client.Client]: Factory method 'stormpathClient' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stormpathClientApiKey' defined in class path resource [com/stormpath/spring/boot/autoconfigure/StormpathAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.stormpath.sdk.api.ApiKey]: Factory method 'stormpathClientApiKey' threw exception; nested exception is java.lang.IllegalStateException: Unable to find an API Key 'id', either from explicit configuration (for example, ApiKeyBuilder.setApiKeyId) or from fallback locations:

1) system property stormpath.client.apiKey.id
2) resource file path or URL specified by system property stormpath.client.apiKey.file
3) resource file path or URL specified by environment variable STORMPATH_API_KEY_FILE
4) environment variable STORMPATH_API_KEY_ID
5) default apiKey.properties file location /Users/snicoll/.stormpath/apiKey.properties.

Please ensure you manually configure an API Key ID or ensure that it exists in one of these fallback locations.
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]

That exception is happening at a weird place, which makes the tomcat starter log it at error level. The IllegalStateException is then thrown and wrapped in the container-specific exception type. And logged again...

Two things:

  • Can you please rework the logic where this exception is thrown so that it happens sooner? Validating the configuration can be enough. That way the exception happens sooner and isn't logged by the embedded container
  • Please provide a dedicated exception type (that contains additional information maybe?) and provide a FailureAnalyzer for it. That way, that huge exception will be replaced with a very concise message at the bottom of the logs that the user will see immediately. You can easily create your own FailureAnalyzer

Another way to deal with this issue is to back-off until you get the data that you need. You could move all that logic in a custom condition and disable the auto-configuration if that information isn't available. But I guess the current code is failing on purpose...

snicoll avatar Jan 31 '17 07:01 snicoll

Thanks for the feedback @snicoll. We are reviewing the issue.

dogeared avatar Feb 01 '17 16:02 dogeared