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

CastClass exception when wiring Map of beans (NullBean instead of 'null' in the map) [SPR-16033] #20582

Closed
spring-issuemaster opened this issue Oct 2, 2017 · 13 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

commented Oct 2, 2017

Francisco Lozano opened SPR-16033 and commented

Offending code has been working since 4.1 at least, up until 5.0.0.RC3. It just started failing in GA.

java.lang.IllegalStateException: Failed to load ApplicationContext
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:107)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
	at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
	at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:242)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.mycompany.platform.server.healthcheck.HealthcheckConfiguration': Unsatisfied dependency expressed through field 'healthcheckConfigSets'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'eventListenerAdapterHealthcheckConfigSet' defined in class path resource [com/mycompany/platform/event/provider/EventBusHealthcheckConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mycompany.common.healthcheck.service.HealthcheckConfigSet]: Factory method 'eventListenerAdapterHealthcheckConfigSet' threw exception; nested exception is java.lang.ClassCastException: org.springframework.beans.factory.support.NullBean cannot be cast to com.mycompany.platform.event.bus.EventListenerAdapter
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:581)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:367)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1340)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:756)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
	at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
	at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:246)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
	... 26 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'eventListenerAdapterHealthcheckConfigSet' defined in class path resource [com/mycompany/platform/event/provider/EventBusHealthcheckConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mycompany.common.healthcheck.service.HealthcheckConfigSet]: Factory method 'eventListenerAdapterHealthcheckConfigSet' threw exception; nested exception is java.lang.ClassCastException: org.springframework.beans.factory.support.NullBean cannot be cast to com.mycompany.platform.event.bus.EventListenerAdapter
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:583)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1249)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1098)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1320)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1286)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1188)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1091)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1060)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:578)
	... 44 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mycompany.common.healthcheck.service.HealthcheckConfigSet]: Factory method 'eventListenerAdapterHealthcheckConfigSet' threw exception; nested exception is java.lang.ClassCastException: org.springframework.beans.factory.support.NullBean cannot be cast to com.mycompany.platform.event.bus.EventListenerAdapter
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:186)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:575)
	... 59 more
Caused by: java.lang.ClassCastException: org.springframework.beans.factory.support.NullBean cannot be cast to com.mycompany.platform.event.bus.EventListenerAdapter
	at com.mycompany.platform.event.provider.EventBusHealthcheckConfiguration.eventListenerAdapterHealthcheckConfigSet(EventBusHealthcheckConfiguration.java:49)
	at com.mycompany.platform.event.provider.EventBusHealthcheckConfiguration$$EnhancerBySpringCGLIB$$a46517a5.CGLIB$eventListenerAdapterHealthcheckConfigSet$1(<generated>)
	at com.mycompany.platform.event.provider.EventBusHealthcheckConfiguration$$EnhancerBySpringCGLIB$$a46517a5$$FastClassBySpringCGLIB$$e3074686.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
	at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
	at com.mycompany.platform.event.provider.EventBusHealthcheckConfiguration$$EnhancerBySpringCGLIB$$a46517a5.eventListenerAdapterHealthcheckConfigSet(<generated>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:155)
	... 60 more

Offending bean is defined as:

	@Bean
	@Profile("BATCH")
	HealthcheckConfigSet eventListenerAdapterHealthcheckConfigSet(
			@Autowired(required = false) @Lazy Map<String, EventListenerAdapter> eventListenerAdapters) {
		if (eventListenerAdapters == null || eventListenerAdapters.isEmpty()) {
			return null;
		}

		HealthcheckConfigSet set = new HealthcheckConfigSet(HealthcheckGroup.HEALTH);
		for (Entry<String, EventListenerAdapter> a : eventListenerAdapters.entrySet()) {
			if (a.getValue() == null) {
				LOGGER.info("Cannot configure healthcheck for EventListenerAdapter {}: the adapter is null",
						a.getKey());
				continue;
			} else {
				LOGGER.info("Configuring healthcheck for EventListenerAdapter {}", a.getKey());
				Healthcheck hc = new EventListenerAdapterHealthcheck(a.getKey(), a.getValue());
				set.add("event-listener-adapter-" + a.getKey(), hc);
			}

		}
		return set;
	}

From the code, I understand that at some point the Map contained null values, and now it seems the map contains NullBean instances.


Affects: 5.0 GA

Issue Links:

  • #20384 Autowire contract is not honored in cases where FactoryBean or @Bean return null
  • #20889 BeanNotOfRequiredTypeException (NullBean instead of null) when calling ApplicationContext.getBean(name, type)
  • #20612 BeanDefinitionValidationException when beans are null (NullBean) and initMethod is set
  • #20711 CastClass exception (NullBean instead of 'null' value) when getting map of beans directly from ApplicationContext
  • #20797 null FactoryBean results in BeanCreationException
  • #21572 Consistent non-exposure of null beans in the BeanFactory API

Referenced from: commits c9d3c26

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 2, 2017

Francisco Lozano commented

Fixing temporarily as:

	@Bean
	@Profile("BATCH")
	HealthcheckConfigSet eventListenerAdapterHealthcheckConfigSet(
			@Autowired(required = false) @Lazy Map<String, EventListenerAdapter> eventListenerAdapters) {
		if (eventListenerAdapters == null || eventListenerAdapters.isEmpty()) {
			return null;
		}

		HealthcheckConfigSet set = new HealthcheckConfigSet(HealthcheckGroup.HEALTH);
		for (Entry<String, EventListenerAdapter> a : eventListenerAdapters.entrySet()) {
			String key = a.getKey();
			EventListenerAdapter value;
			// TODO remove this when #20582 is solved
			try {
				value = a.getValue();
			} catch (ClassCastException e) {
				LOGGER.info("Cannot configure healthcheck for EventListenerAdapter " + key, e);
				continue;
			}
			if (value == null) {
				LOGGER.info("Cannot configure healthcheck for EventListenerAdapter {}: the adapter is null", key);
				continue;
			} else {
				LOGGER.info("Configuring healthcheck for EventListenerAdapter {}", key);
				Healthcheck hc = new EventListenerAdapterHealthcheck(key, value);
				set.add("event-listener-adapter-" + key, hc);
			}

		}
		return set;
	}
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 2, 2017

Francisco Lozano commented

Also reproduced somewhere else (in test code) by doing:

Map<String, EventListenerAdapter> beanMap = ctx.getBeansOfType(EventListenerAdapter.class);
com.mycompany.platform.product.server.services.BatchProfileTest > activated FAILED
    org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'mongoDBIndexerEventListenerAdapter' is expected to be of type 'com.mycompany.platform.event.bus.EventListenerAdapter' but was actually of type 'org.springframework.beans.factory.support.NullBean'
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:384)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:515)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:504)
        at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1192)
        at com.mycompany.platform.product.server.services.BatchProfileTest.activated(BatchProfileTest.java:44)
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 2, 2017

Juergen Hoeller commented

This is indeed a consequence of a recent change where we're never exposing null values as a bean instance internally. For external consumption, we're still exposing those as null, so it seems we missed the Map injection case there...

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 2, 2017

Francisco Lozano commented

One question: if I change the Map<String,TypeOfBean> to Map<String,Optional<TypeOfBean>>, will I get it right? it could mitigate my case in a cleaner way.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Oct 2, 2017

Juergen Hoeller commented

We don't support nested Optional declarations that way, I'm afraid. The proper fix is on our end, simply resolving null values accordingly, which I have fixed for 5.0.1 now. Please give the upcoming 5.0.1.BUILD-SNAPSHOT a try if you have a chance.

That said, on your end, I avoid null values in your context setup to begin with. I'd rather expose a dummy listener instance (or whatever it is) instead of a null value from your factory method or FactoryBean.getObject() implementation.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Francisco Lozano commented

I'm still getting this:

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'mongoDBIndexerEventListenerAdapter' is expected to be of type 'com.kii.platform.ufp.event.bus.EventListenerAdapter' but was actually of type 'org.springframework.beans.factory.support.NullBean'
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:384)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:515)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:504)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1192)
	at com.mycompany.platform.ufp.ufe.server.services.BatchProfileTest.activated(BatchProfileTest.java:44)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:539)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:761)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:461)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:207)

Line 44 is:

		Map<String, EventListenerAdapter> beanMap = ctx.getBeansOfType(EventListenerAdapter.class);
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Francisco Lozano commented

(Using Spring 5.0.1.RELEASE).

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Juergen Hoeller commented

Francisco Lozano, could you please create a separate follow-up issue for this specific case? Indeed, getBeansOfType still doesn't leniently handle null instances yet since that 5.0.1 fix just applied to @Autowired resolution... Let's fix this for getBeansOfType as well but ideally under a separate JIRA ticket, then marked for 5.0.2.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Francisco Lozano commented

I CANNOT reproduce with very simple code, however:

@Configuration
public class ConfigClass {
	@Bean
	public Dummy bean1() {
		return new Dummy();
	}

	@Bean
	public Dummy bean2() {
		return new Dummy();
	}

	@Bean
	public Dummy bean3() {
		return new Dummy();
	}

	@Bean
	public Object bean4() {
		return null;
	}
}
		try (AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext()) {
			ctx.register(ConfigClass.class);
			ctx.refresh();
			Map<String, Dummy> beans = ctx.getBeansOfType(Dummy.class);
			assertNotNull(beans.get("bean1"));
			assertNotNull(beans.get("bean2"));
			assertNotNull(beans.get("bean3"));
			assertNull(beans.get("bean4"));

		}
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Juergen Hoeller commented

I've managed to reproduce it next to my @Autowired test case already, and it's also straightforward to fix. It'd be great to have a separate JIRA issue for tracking it though :-)

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Francisco Lozano commented

spring-projects/spring-framework-issues#173 managed to reproduce too. I'll open a new issue.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Juergen Hoeller commented

Yes please. For better or for worse, @Autowired collection resolution and getBeansOfType are separate code paths. So let's keep this issue for the @Autowired fix (5.0.1) and the new issue for the getBeansOfType fix (5.0.2).

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Nov 6, 2017

Francisco Lozano commented

#20711 here it is. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.