LGTM :) On Fri, 4 Jun 2021 at 19:47, Martin Grigorov <mgrigo...@apache.org> wrote:
> The other day while working on s/SpringBean/Inject/ I've faced a problem in > org.apache.wicket.spring.SpringBeanLocator#getBeanDefinition() - it failed > with ClassCastException that ApplicationContextMock is not an > AbstractApplicationContext > > What do you think about this change ? > It allows to implement almost all methods in ApplicationContextMock and to > use it here [1] and here [2] > > 1. > > https://github.com/apache/wicket/blob/67165d1820d247286f5c12c1755fe11424a74046/wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/AnnotProxyFieldValueFactory.java#L233 > 2. > > https://github.com/apache/wicket/blob/67165d1820d247286f5c12c1755fe11424a74046/wicket-spring/src/main/java/org/apache/wicket/spring/injection/annot/AnnotProxyFieldValueFactory.java#L252 > > On Fri, Jun 4, 2021 at 3:42 PM <mgrigo...@apache.org> wrote: > > > This is an automated email from the ASF dual-hosted git repository. > > > > mgrigorov pushed a commit to branch > > make-spring-applicationcontextmock-smarter > > in repository https://gitbox.apache.org/repos/asf/wicket.git > > > > commit 7839f8887184f5c19767c8e9b31d79dd896d45d1 > > Author: Martin Tzvetanov Grigorov <mgrigo...@apache.org> > > AuthorDate: Fri Jun 4 15:36:06 2021 +0300 > > > > Use DefaultListableBeanFactory as a delegate in > ApplicationContextMock > > > > This way ApplicationContextMock could provide implementation for more > > of its methods and more importantly > SpringBeanLocation#getBeanDefinition() > > [1] could work with it, also two more places in > > org.apache.wicket.spring.injection.annot.AnnotProxyFieldValueFactory will > > use it > > > > 1. > > > https://github.com/apache/wicket/blob/8d44c5b5094cccc9d5e05408e42ccc1bd0dd4da6/wicket-spring/src/main/java/org/apache/wicket/spring/SpringBeanLocator.java#L421 > > --- > > .../wicket/spring/test/ApplicationContextMock.java | 235 > > +++++---------------- > > 1 file changed, 57 insertions(+), 178 deletions(-) > > > > diff --git > > > a/wicket-spring/src/main/java/org/apache/wicket/spring/test/ApplicationContextMock.java > > > b/wicket-spring/src/main/java/org/apache/wicket/spring/test/ApplicationContextMock.java > > index 5d285f7..d5a83f8 100644 > > --- > > > a/wicket-spring/src/main/java/org/apache/wicket/spring/test/ApplicationContextMock.java > > +++ > > > b/wicket-spring/src/main/java/org/apache/wicket/spring/test/ApplicationContextMock.java > > @@ -19,45 +19,44 @@ package org.apache.wicket.spring.test; > > import java.io.IOException; > > import java.io.Serializable; > > import java.lang.annotation.Annotation; > > -import java.util.ArrayList; > > -import java.util.HashMap; > > -import java.util.Iterator; > > import java.util.Locale; > > import java.util.Map; > > -import java.util.Map.Entry; > > > > import org.springframework.beans.BeansException; > > import org.springframework.beans.factory.BeanFactory; > > -import org.springframework.beans.factory.BeanNotOfRequiredTypeException; > > -import org.springframework.beans.factory.FactoryBean; > > import org.springframework.beans.factory.NoSuchBeanDefinitionException; > > import org.springframework.beans.factory.ObjectProvider; > > import > > org.springframework.beans.factory.config.AutowireCapableBeanFactory; > > +import > > org.springframework.beans.factory.config.ConfigurableListableBeanFactory; > > +import > > org.springframework.beans.factory.support.DefaultListableBeanFactory; > > +import org.springframework.beans.factory.support.RootBeanDefinition; > > import org.springframework.context.ApplicationContext; > > import org.springframework.context.ApplicationEvent; > > import org.springframework.context.MessageSourceResolvable; > > import org.springframework.context.NoSuchMessageException; > > +import org.springframework.context.support.AbstractApplicationContext; > > import org.springframework.core.ResolvableType; > > -import org.springframework.core.env.Environment; > > import org.springframework.core.io.Resource; > > > > /** > > * Mock application context object. This mock context allows easy > > creation of unit tests by allowing > > * the user to put bean instances into the context. > > * > > - * Only {@link #getBean(String)}, {@link #getBean(String, Class)}, and > > - * {@link #getBeansOfType(Class) > > - * } are implemented so far. Any other method throws > > - * {@link UnsupportedOperationException}. > > - * > > * @author Igor Vaynberg (ivaynberg) > > * > > */ > > -public class ApplicationContextMock implements ApplicationContext, > > Serializable > > +public class ApplicationContextMock extends AbstractApplicationContext > > implements Serializable > > { > > private static final long serialVersionUID = 1L; > > > > - private final Map<String, Object> beans = new HashMap<>(); > > + private final DefaultListableBeanFactory beanFactory; > > + private final long startupTime; > > + > > + public ApplicationContextMock() { > > + this.beanFactory = new DefaultListableBeanFactory(); > > + > > beanFactory.setSerializationId(ApplicationContextMock.class.getName()); > > + startupTime = System.currentTimeMillis(); > > + } > > > > /** > > * puts bean with the given name into the context > > @@ -65,14 +64,9 @@ public class ApplicationContextMock implements > > ApplicationContext, Serializable > > * @param name > > * @param bean > > */ > > - public void putBean(final String name, final Object bean) > > + public <T extends Object> void putBean(final String name, final T > > bean) > > { > > - if (beans.containsKey(name)) > > - { > > - throw new IllegalArgumentException("a bean with > > name [" + name + > > - "] has already been added to the > context"); > > - } > > - beans.put(name, bean); > > + beanFactory.registerBeanDefinition(name, new > > RootBeanDefinition((Class<T>)bean.getClass(), () -> bean)); > > } > > > > /** > > @@ -88,159 +82,82 @@ public class ApplicationContextMock implements > > ApplicationContext, Serializable > > @Override > > public Object getBean(final String name) throws BeansException > > { > > - Object bean = beans.get(name); > > - if (bean == null) > > - { > > - throw new NoSuchBeanDefinitionException(name); > > - } > > - return bean; > > + return beanFactory.getBean(name); > > } > > > > @Override > > public Object getBean(final String name, final Object... args) > > throws BeansException > > { > > - return getBean(name); > > + return beanFactory.getBean(name, args); > > } > > > > - /** > > - * @see > > org.springframework.beans.factory.BeanFactory#getBean(java.lang.String, > > java.lang.Class) > > - */ > > @Override > > @SuppressWarnings({ "unchecked" }) > > public <T> T getBean(String name, Class<T> requiredType) throws > > BeansException > > { > > - Object bean = getBean(name); > > - if (!(requiredType.isAssignableFrom(bean.getClass()))) > > - { > > - throw new BeanNotOfRequiredTypeException(name, > > requiredType, bean.getClass()); > > - } > > - return (T)bean; > > + return beanFactory.getBean(name, requiredType); > > } > > > > - /** > > - * @see > > > org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(java.lang.Class) > > - */ > > @Override > > @SuppressWarnings({ "unchecked" }) > > public <T> Map<String, T> getBeansOfType(Class<T> type) throws > > BeansException > > { > > - final Map<String, T> found = new HashMap<>(); > > - > > - for (Entry<String, Object> entry : beans.entrySet()) > > - { > > - if > > (type.isAssignableFrom(entry.getValue().getClass())) > > - { > > - found.put(entry.getKey(), > > (T)entry.getValue()); > > - } > > - } > > - > > - return found; > > + return beanFactory.getBeansOfType(type); > > } > > > > @Override > > public <T> T getBean(Class<T> requiredType) throws BeansException > > { > > - Iterator<T> beans = > > getBeansOfType(requiredType).values().iterator(); > > - > > - if (beans.hasNext() == false) > > - { > > - throw new NoSuchBeanDefinitionException("bean of > > required type " + requiredType + > > - " not found"); > > - } > > - final T bean = beans.next(); > > - > > - if (beans.hasNext() != false) > > - { > > - throw new NoSuchBeanDefinitionException("more > than > > one bean of required type " + > > - requiredType + " found"); > > - } > > - return bean; > > + return beanFactory.getBean(requiredType); > > } > > > > @Override > > public <T> T getBean(Class<T> requiredType, Object... objects) > > throws BeansException > > { > > - return getBean(requiredType); > > + return beanFactory.getBean(requiredType, objects); > > } > > > > @Override > > public <T> ObjectProvider<T> getBeanProvider(Class<T> aClass) > > { > > - return null; > > + return beanFactory.getBeanProvider(aClass); > > } > > > > @Override > > public <T> ObjectProvider<T> getBeanProvider(ResolvableType > > resolvableType) > > { > > - return null; > > + return beanFactory.getBeanProvider(resolvableType); > > } > > > > @Override > > public Map<String, Object> getBeansWithAnnotation(Class<? extends > > Annotation> annotationType) > > throws BeansException > > { > > - final Map<String, Object> found = new HashMap<>(); > > - > > - for (Entry<String, Object> entry : beans.entrySet()) > > - { > > - if > > (entry.getValue().getClass().isAnnotationPresent(annotationType)) > > - { > > - found.put(entry.getKey(), > > entry.getValue()); > > - } > > - } > > - return found; > > + return > beanFactory.getBeansWithAnnotation(annotationType); > > } > > > > @Override > > public <A extends Annotation> A findAnnotationOnBean(String > > beanName, Class<A> annotationType) > > { > > - return > findAnnotationOnClass(getBean(beanName).getClass(), > > annotationType); > > - } > > - > > - private <A extends Annotation> A findAnnotationOnClass(Class<?> > > cls, Class<A> annotationType) > > - { > > - // lookup annotation type on class > > - A annotation = cls.getAnnotation(annotationType); > > - > > - // lookup annotation type on superclass > > - if (annotation == null && cls.getSuperclass() != null) > > - { > > - annotation = > > findAnnotationOnClass(cls.getSuperclass(), annotationType); > > - } > > - > > - // lookup annotation type on interfaces > > - if (annotation == null) > > - { > > - for (Class<?> intfClass : cls.getInterfaces()) > > - { > > - annotation = > > findAnnotationOnClass(intfClass, annotationType); > > - > > - if (annotation != null) > > - { > > - break; > > - } > > - } > > - } > > - > > - return annotation; > > + return beanFactory.findAnnotationOnBean(beanName, > > annotationType); > > } > > > > @Override > > public ApplicationContext getParent() > > { > > - throw new UnsupportedOperationException(); > > + return null; > > } > > > > @Override > > public String getDisplayName() > > { > > - throw new UnsupportedOperationException(); > > + return ApplicationContextMock.class.getSimpleName(); > > } > > > > @Override > > public long getStartupDate() > > { > > - throw new UnsupportedOperationException(); > > + return startupTime; > > } > > > > @Override > > @@ -258,129 +175,103 @@ public class ApplicationContextMock implements > > ApplicationContext, Serializable > > @Override > > public boolean containsBeanDefinition(final String beanName) > > { > > - return containsBean(beanName); > > + return beanFactory.containsBean(beanName); > > } > > > > @Override > > public int getBeanDefinitionCount() > > { > > - return beans.size(); > > + return beanFactory.getBeanDefinitionCount(); > > } > > > > @Override > > public String[] getBeanDefinitionNames() > > { > > - return beans.keySet().toArray(new String[0]); > > + return beanFactory.getBeanDefinitionNames(); > > } > > > > @Override > > public <T> ObjectProvider<T> getBeanProvider(final Class<T> > > aClass, final boolean b) { > > - return null; > > + return beanFactory.getBeanProvider(aClass, b); > > } > > > > @Override > > public <T> ObjectProvider<T> getBeanProvider(final ResolvableType > > resolvableType, final boolean b) { > > - return null; > > + return beanFactory.getBeanProvider(resolvableType, b); > > } > > > > @Override > > public String[] getBeanNamesForType(ResolvableType > resolvableType) > > { > > - return new String[0]; > > + return beanFactory.getBeanNamesForType(resolvableType); > > } > > > > @Override > > public String[] getBeanNamesForType(ResolvableType > resolvableType, > > boolean includeNonSingletons, boolean allowEagerInit) > > { > > - return new String[0]; > > + return beanFactory.getBeanNamesForType(resolvableType, > > includeNonSingletons, allowEagerInit); > > } > > > > @Override > > - @SuppressWarnings({ "unchecked" }) > > public String[] getBeanNamesForType(final Class type) > > { > > - ArrayList<String> names = new ArrayList<>(); > > - for (Entry<String, Object> entry : beans.entrySet()) > > - { > > - Object bean = entry.getValue(); > > - > > - if (type.isAssignableFrom(bean.getClass())) > > - { > > - names.add(entry.getKey()); > > - } > > - } > > - return names.toArray(new String[names.size()]); > > + return beanFactory.getBeanNamesForType(type); > > } > > > > @Override > > - @SuppressWarnings({ "unchecked" }) > > public String[] getBeanNamesForType(Class type, boolean > > includeNonSingletons, > > boolean allowEagerInit) > > { > > - throw new UnsupportedOperationException(); > > + return beanFactory.getBeanNamesForType(type, > > includeNonSingletons, allowEagerInit); > > } > > > > @Override > > public <T> Map<String, T> getBeansOfType(Class<T> type, boolean > > includeNonSingletons, > > boolean allowEagerInit) throws BeansException > > { > > - throw new UnsupportedOperationException(); > > + return beanFactory.getBeansOfType(type, > > includeNonSingletons, allowEagerInit); > > } > > > > @Override > > public String[] getBeanNamesForAnnotation(Class<? extends > > Annotation> aClass) > > { > > - throw new UnsupportedOperationException(); > > + return beanFactory.getBeanNamesForAnnotation(aClass); > > } > > > > @Override > > public boolean containsBean(final String name) > > { > > - return beans.containsKey(name); > > + return beanFactory.containsBean(name); > > } > > > > @Override > > public boolean isSingleton(final String name) throws > > NoSuchBeanDefinitionException > > { > > - return true; > > + return beanFactory.isSingleton(name); > > } > > > > @Override > > public Class<?> getType(final String name) throws > > NoSuchBeanDefinitionException > > { > > - return getType(name, true); > > + return beanFactory.getType(name); > > } > > > > @Override > > public Class<?> getType(String name, boolean > allowFactoryBeanInit) > > throws NoSuchBeanDefinitionException > > { > > - Object bean = beans.get(name); > > - if (bean == null) > > - { > > - throw new NoSuchBeanDefinitionException("No bean > > with name '" + name + "'"); > > - } > > - > > - if (bean instanceof FactoryBean) > > - { > > - return ((FactoryBean) bean).getObjectType(); > > - } > > - > > - return bean.getClass(); > > + return beanFactory.getType(name, allowFactoryBeanInit); > > } > > > > @Override > > public String[] getAliases(final String name) throws > > NoSuchBeanDefinitionException > > { > > - throw new UnsupportedOperationException(); > > + return beanFactory.getAliases(name); > > } > > > > - /** > > - * @see > org.springframework.beans.factory.HierarchicalBeanFactory# > > getParentBeanFactory() > > - */ > > @Override > > public BeanFactory getParentBeanFactory() > > { > > - return null; > > + return beanFactory.getParentBeanFactory(); > > } > > > > @Override > > @@ -411,64 +302,52 @@ public class ApplicationContextMock implements > > ApplicationContext, Serializable > > } > > > > @Override > > - public Resource getResource(final String location) > > - { > > - throw new UnsupportedOperationException(); > > + protected void refreshBeanFactory() throws BeansException, > > IllegalStateException { > > } > > > > @Override > > - public AutowireCapableBeanFactory getAutowireCapableBeanFactory() > > throws IllegalStateException > > - { > > - throw new UnsupportedOperationException(); > > + protected void closeBeanFactory() { > > } > > > > @Override > > - public boolean containsLocalBean(final String arg0) > > - { > > - throw new UnsupportedOperationException(); > > + public ConfigurableListableBeanFactory getBeanFactory() throws > > IllegalStateException { > > + return beanFactory; > > } > > > > @Override > > - public ClassLoader getClassLoader() > > + public Resource getResource(final String location) > > { > > throw new UnsupportedOperationException(); > > } > > > > @Override > > - public String getId() > > + public AutowireCapableBeanFactory getAutowireCapableBeanFactory() > > throws IllegalStateException > > { > > - return null; > > + return beanFactory; > > } > > > > @Override > > - public String getApplicationName() > > + public boolean containsLocalBean(final String name) > > { > > - return ""; > > + return beanFactory.containsLocalBean(name); > > } > > > > @Override > > public boolean isPrototype(final String name) throws > > NoSuchBeanDefinitionException > > { > > - return !isSingleton(name); > > + return beanFactory.isPrototype(name); > > } > > > > @Override > > public boolean isTypeMatch(String s, ResolvableType > > resolvableType) throws NoSuchBeanDefinitionException > > { > > - return false; > > + return beanFactory.isTypeMatch(s, resolvableType); > > } > > > > @Override > > - @SuppressWarnings({ "unchecked" }) > > public boolean isTypeMatch(final String name, final Class > > targetType) > > throws NoSuchBeanDefinitionException > > { > > - throw new UnsupportedOperationException(); > > - } > > - > > - @Override > > - public Environment getEnvironment() > > - { > > - return null; > > + return beanFactory.isTypeMatch(name, targetType); > > } > > } > > > -- Best regards, Maxim