Search code examples
javadependency-injectionapache-minaordered-mapapache-aries

Apache Mina Integration With Aries blueprint have problem


https://mina.apache.org/mina-project/userguide/ch17-spring-integration/ch17-spring-integration.html

the user guide of the link, it wrote it works for all DI frameworks.

but The following error occurs when injecting through the Aries Blueprint and is not initialized.

        2022-02-09T11:59:53,554 | ERROR | Blueprint Extender: 3 | BlueprintContainerImpl | 60 - org.apache.aries.blueprint.core - 1.10.3 | Unable to start container for blueprint bundle io-bridge/0.0.1.SNAPSHOT
            org.osgi.service.blueprint.container.ComponentDefinitionException: Error setting property: PropertyDescriptor <name: filters, getter: null, setter: [class org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder.setFilters(interface java.util.Map)]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:818) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:784) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:765) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:699) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:666) ~[!/:1.10.3]
                at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:81) ~[!/:1.10.3]
                at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
                at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:90) ~[!/:1.10.3]
                at org.apache.aries.blueprint.di.RefRecipe.internalCreate(RefRecipe.java:62) ~[!/:1.10.3]
                at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:108) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:810) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:784) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:765) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:699) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:666) ~[!/:1.10.3]
                at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:81) ~[!/:1.10.3]
                at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
                at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:90) ~[!/:1.10.3]
                at org.apache.aries.blueprint.di.RefRecipe.internalCreate(RefRecipe.java:62) ~[!/:1.10.3]
                at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:108) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:810) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:784) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:765) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:699) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:666) ~[!/:1.10.3]
                at org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:81) ~[!/:1.10.3]
                at java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[?:?]
                at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:90) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:360) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:190) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:737) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:433) [!/:1.10.3]
                at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:298) [!/:1.10.3]
                at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
                at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
                at org.apache.aries.blueprint.container.ExecutorServiceWrapper.run(ExecutorServiceWrapper.java:106) [!/:1.10.3]
                at org.apache.aries.blueprint.utils.threading.impl.DiscardableRunnable.run(DiscardableRunnable.java:45) [!/:1.10.3]
                at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
                at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
                at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
                at java.lang.Thread.run(Thread.java:834) [?:?]
            Caused by: java.lang.IllegalArgumentException: filters is not an ordered map. Please try java.util.LinkedHashMap.
                at org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder.setFilters(DefaultIoFilterChainBuilder.java:428) ~[?:?]
                at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
                at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
                at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
                at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?]
                at org.apache.aries.blueprint.utils.ReflectionUtils$MethodPropertyDescriptor.internalSet(ReflectionUtils.java:668) ~[!/:1.10.3]
                at org.apache.aries.blueprint.utils.ReflectionUtils$PropertyDescriptor.set(ReflectionUtils.java:418) ~[!/:1.10.3]
                at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:816) ~[!/:1.10.3]
                ... 42 more

This is the xml syntax for the contents of the error.

        <bean id="myCodec" class="org.apache.mina.filter.codec.ProtocolCodecFilter">
            <argument>
                <bean class="com.my.project.core.message.RProtocolCodecFactory"/>
            </argument>
        </bean>
        
        <bean id="filters" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
            <property name="filters">
                <map key-type="java.lang.String" value-type="org.apache.mina.filter.codec.ProtocolCodecFilter">
                    <entry key="codecFilter" value-ref="myCodec"/>
                </map>
            </property>
        </bean>

When change log level debug, I see the following log.

DEBUG [Blueprint Extender: 1] java.util.HashMap is not a LinkedHashMap.

DEBUG [Blueprint Extender: 1] java.util.HashMap doesn't implement OrderedMap interface.

DEBUG [Blueprint Extender: 1] Last resort; trying to create a new map instance with a default constructor and test if insertion order is maintained.

DEBUG [Blueprint Extender: 1] The specified map didn't pass the insertion order test after 3 tries.

this DEBUG log wrote in org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder.java

There are annotations and method like this in the class.

    @SuppressWarnings("unchecked")
    private boolean isOrderedMap(Map<String,? extends IoFilter> map) {
        if (map == null) {
            return false;
        }
        
        Class<?> mapType = map.getClass();
        
        if (LinkedHashMap.class.isAssignableFrom(mapType)) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("{} is an ordered map.", mapType.getSimpleName() );
            }
            
            return true;
        }

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("{} is not a {}", mapType.getName(), LinkedHashMap.class.getSimpleName());
        }

        // Detect Jakarta Commons Collections OrderedMap implementations.
        Class<?> type = mapType;
        
        while (type != null) {
            for (Class<?> i : type.getInterfaces()) {
                if (i.getName().endsWith("OrderedMap")) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("{} is an ordered map (guessed from that it implements OrderedMap interface.)",
                                mapType.getSimpleName());
                    }
                    
                    return true;
                }
            }
            
            type = type.getSuperclass();
        }

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("{} doesn't implement OrderedMap interface.", mapType.getName() );
        }

        // Last resort: try to create a new instance and test if it maintains
        // the insertion order.
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Last resort; trying to create a new map instance with a "
                    + "default constructor and test if insertion order is maintained.");
        }

        Map<String,IoFilter> newMap;
        
        try {
            newMap = (Map<String,IoFilter>) mapType.newInstance();
        } catch (Exception e) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Failed to create a new map instance of '{}'.", mapType.getName(), e);
            }
            
            return false;
        }

        Random rand = new Random();
        List<String> expectedNames = new ArrayList<>();
        IoFilter dummyFilter = new IoFilterAdapter();
        
        for (int i = 0; i < 65536; i++) {
            String filterName;
            
            do {
                filterName = String.valueOf(rand.nextInt());
            } while (newMap.containsKey(filterName));

            newMap.put(filterName, dummyFilter);
            expectedNames.add(filterName);

            Iterator<String> it = expectedNames.iterator();
            
            for (Object key : newMap.keySet()) {
                if (!it.next().equals(key)) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("The specified map didn't pass the insertion order test after {} tries.", (i + 1));
                    }
                    
                    return false;
                }
            }
        }

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("The specified map passed the insertion order test.");
        }
        
        return true;
    }

"Detect Jakarta Commons Collections OrderedMap implementations"

If the injected type is not OrderedMap, can see that trying to create a new Map.

When using the existing Spring DM property, it is expected to create the same new map and try it, but there was no failure.

Why? Do I fail when I use Blueprint Property?

What am I missing? Is there a better alternative?


Solution

  • When I came back from solving other problems for a few days, I looked at the guide document of OSGI 7 standard and it was a very simple problem.

    <bean id="filter" class="java.util.LinkedHashMap">
        <argument>
            <map>
                <entry key="codecFilter" value-ref="dfCodec"/>
            </map>
        </argument>
    
    </bean>
    
    <bean id="filters"
          class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder">
        <property name="filters" ref="filter"/>
    </bean>
    

    it works well