Example usage for org.springframework.integration.util UniqueMethodFilter UniqueMethodFilter

List of usage examples for org.springframework.integration.util UniqueMethodFilter UniqueMethodFilter

Introduction

In this page you can find the example usage for org.springframework.integration.util UniqueMethodFilter UniqueMethodFilter.

Prototype

public UniqueMethodFilter(Class<?> targetClass) 

Source Link

Usage

From source file:org.springframework.integration.handler.support.MessagingMethodInvokerHelper.java

private Map<String, Map<Class<?>, HandlerMethod>> findHandlerMethodsForTarget(final Object targetObject,
        final Class<? extends Annotation> annotationType, final String methodNameToUse,
        final boolean requiresReply) {

    Map<String, Map<Class<?>, HandlerMethod>> handlerMethods = new HashMap<>();

    final Map<Class<?>, HandlerMethod> candidateMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> candidateMessageMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> fallbackMethods = new HashMap<>();
    final Map<Class<?>, HandlerMethod> fallbackMessageMethods = new HashMap<>();
    final AtomicReference<Class<?>> ambiguousFallbackType = new AtomicReference<>();
    final AtomicReference<Class<?>> ambiguousFallbackMessageGenericType = new AtomicReference<>();
    final Class<?> targetClass = getTargetClass(targetObject);

    final String methodName;

    if (methodNameToUse == null) {
        if (Function.class.isAssignableFrom(targetClass)) {
            methodName = "apply";
        } else if (Consumer.class.isAssignableFrom(targetClass)) {
            methodName = "accept";
        } else {//from   ww w  .  j a  v  a  2  s  .  c  o  m
            methodName = null;
        }
    } else {
        methodName = methodNameToUse;
    }

    MethodFilter methodFilter = new UniqueMethodFilter(targetClass);
    ReflectionUtils.doWithMethods(targetClass, method1 -> {
        boolean matchesAnnotation = false;
        if (method1.isBridge()) {
            return;
        }
        if (isMethodDefinedOnObjectClass(method1)) {
            return;
        }
        if (method1.getDeclaringClass().equals(Proxy.class)) {
            return;
        }
        if (annotationType != null && AnnotationUtils.findAnnotation(method1, annotationType) != null) {
            matchesAnnotation = true;
        } else if (!Modifier.isPublic(method1.getModifiers())) {
            return;
        }
        if (requiresReply && void.class.equals(method1.getReturnType())) {
            return;
        }
        if (methodName != null && !methodName.equals(method1.getName())) {
            return;
        }
        if (methodName == null && ObjectUtils.containsElement(new String[] { "start", "stop", "isRunning" },
                method1.getName())) {
            return;
        }
        HandlerMethod handlerMethod1;
        try {
            method1 = AopUtils.selectInvocableMethod(method1,
                    org.springframework.util.ClassUtils.getUserClass(targetObject));
            InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
                    .createInvocableHandlerMethod(targetObject, method1);
            handlerMethod1 = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
            checkSpelInvokerRequired(targetClass, method1, handlerMethod1);
        } catch (IneligibleMethodException e) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method [" + method1 + "] is not eligible for Message handling " + e.getMessage()
                        + ".");
            }
            return;
        } catch (Exception e) {
            if (logger.isDebugEnabled()) {
                logger.debug("Method [" + method1 + "] is not eligible for Message handling.", e);
            }
            return;
        }
        if (AnnotationUtils.getAnnotation(method1, Default.class) != null) {
            Assert.state(this.defaultHandlerMethod == null,
                    () -> "Only one method can be @Default, but there are more for: " + targetObject);
            this.defaultHandlerMethod = handlerMethod1;
        }
        Class<?> targetParameterType = handlerMethod1.getTargetParameterType();
        if (matchesAnnotation || annotationType == null) {
            if (handlerMethod1.isMessageMethod()) {
                if (candidateMessageMethods.containsKey(targetParameterType)) {
                    throw new IllegalArgumentException("Found more than one method match for type "
                            + "[Message<" + targetParameterType + ">]");
                }
                candidateMessageMethods.put(targetParameterType, handlerMethod1);
            } else {
                if (candidateMethods.containsKey(targetParameterType)) {
                    String exceptionMessage = "Found more than one method match for ";
                    if (Void.class.equals(targetParameterType)) {
                        exceptionMessage += "empty parameter for 'payload'";
                    } else {
                        exceptionMessage += "type [" + targetParameterType + "]";
                    }
                    throw new IllegalArgumentException(exceptionMessage);
                }
                candidateMethods.put(targetParameterType, handlerMethod1);
            }
        } else {
            if (handlerMethod1.isMessageMethod()) {
                if (fallbackMessageMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackMessageGenericType.compareAndSet(null, targetParameterType);
                }
                fallbackMessageMethods.put(targetParameterType, handlerMethod1);
            } else {
                if (fallbackMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackType.compareAndSet(null, targetParameterType);
                }
                fallbackMethods.put(targetParameterType, handlerMethod1);
            }
        }
    }, methodFilter);

    if (candidateMethods.isEmpty() && candidateMessageMethods.isEmpty() && fallbackMethods.isEmpty()
            && fallbackMessageMethods.isEmpty()) {
        findSingleSpecifMethodOnInterfacesIfProxy(targetObject, methodName, candidateMessageMethods,
                candidateMethods);
    }

    if (!candidateMethods.isEmpty() || !candidateMessageMethods.isEmpty()) {
        handlerMethods.put(CANDIDATE_METHODS, candidateMethods);
        handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
        return handlerMethods;
    }
    if ((ambiguousFallbackType.get() != null || ambiguousFallbackMessageGenericType.get() != null)
            && ServiceActivator.class.equals(annotationType)) {
        /*
         * When there are ambiguous fallback methods,
         * a Service Activator can finally fallback to RequestReplyExchanger.exchange(m).
         * Ambiguous means > 1 method that takes the same payload type, or > 1 method
         * that takes a Message with the same generic type.
         */
        List<Method> frameworkMethods = new ArrayList<>();
        Class<?>[] allInterfaces = org.springframework.util.ClassUtils.getAllInterfacesForClass(targetClass);
        for (Class<?> iface : allInterfaces) {
            try {
                if ("org.springframework.integration.gateway.RequestReplyExchanger".equals(iface.getName())) {
                    frameworkMethods.add(targetClass.getMethod("exchange", Message.class));
                    if (logger.isDebugEnabled()) {
                        logger.debug(targetObject.getClass()
                                + ": Ambiguous fallback methods; using RequestReplyExchanger.exchange()");
                    }
                }
            } catch (Exception e) {
                // should never happen (but would fall through to errors below)
            }
        }
        if (frameworkMethods.size() == 1) {
            Method method = org.springframework.util.ClassUtils.getMostSpecificMethod(frameworkMethods.get(0),
                    targetObject.getClass());
            InvocableHandlerMethod invocableHandlerMethod = this.messageHandlerMethodFactory
                    .createInvocableHandlerMethod(targetObject, method);
            HandlerMethod handlerMethod = new HandlerMethod(invocableHandlerMethod, this.canProcessMessageList);
            checkSpelInvokerRequired(targetClass, method, handlerMethod);
            handlerMethods.put(CANDIDATE_METHODS, Collections.singletonMap(Object.class, handlerMethod));
            handlerMethods.put(CANDIDATE_MESSAGE_METHODS, candidateMessageMethods);
            return handlerMethods;
        }
    }

    Assert.state(!fallbackMethods.isEmpty() || !fallbackMessageMethods.isEmpty(), "Target object of type ["
            + this.targetObject.getClass() + "] has no eligible methods for handling Messages.");

    Assert.isNull(ambiguousFallbackType.get(), "Found ambiguous parameter type [" + ambiguousFallbackType
            + "] for method match: " + fallbackMethods.values());
    Assert.isNull(ambiguousFallbackMessageGenericType.get(), "Found ambiguous parameter type ["
            + ambiguousFallbackMessageGenericType + "] for method match: " + fallbackMethods.values());

    handlerMethods.put(CANDIDATE_METHODS, fallbackMethods);
    handlerMethods.put(CANDIDATE_MESSAGE_METHODS, fallbackMessageMethods);
    return handlerMethods;
}

From source file:org.springframework.integration.util.MessagingMethodInvokerHelper.java

private Map<Class<?>, HandlerMethod> findHandlerMethodsForTarget(final Object targetObject,
        final Class<? extends Annotation> annotationType, final String methodName,
        final boolean requiresReply) {

    final Map<Class<?>, HandlerMethod> candidateMethods = new HashMap<Class<?>, HandlerMethod>();
    final Map<Class<?>, HandlerMethod> fallbackMethods = new HashMap<Class<?>, HandlerMethod>();
    final AtomicReference<Class<?>> ambiguousFallbackType = new AtomicReference<Class<?>>();
    final Class<?> targetClass = this.getTargetClass(targetObject);
    MethodFilter methodFilter = new UniqueMethodFilter(targetClass);
    ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
            boolean matchesAnnotation = false;
            if (method.isBridge()) {
                return;
            }/*from  w  w w. j av  a 2 s . com*/
            if (isMethodDefinedOnObjectClass(method)) {
                return;
            }
            if (method.getDeclaringClass().equals(Proxy.class)) {
                return;
            }
            if (!Modifier.isPublic(method.getModifiers())) {
                return;
            }
            if (requiresReply && void.class.equals(method.getReturnType())) {
                return;
            }
            if (methodName != null && !methodName.equals(method.getName())) {
                return;
            }
            if (annotationType != null && AnnotationUtils.findAnnotation(method, annotationType) != null) {
                matchesAnnotation = true;
            }
            HandlerMethod handlerMethod = null;
            try {
                handlerMethod = new HandlerMethod(method, canProcessMessageList);
            } catch (Exception e) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Method [" + method + "] is not eligible for Message handling.", e);
                }
                return;
            }
            Class<?> targetParameterType = handlerMethod.getTargetParameterType().getObjectType();
            if (matchesAnnotation || annotationType == null) {
                Assert.isTrue(!candidateMethods.containsKey(targetParameterType),
                        "Found more than one method match for type [" + targetParameterType + "]");
                candidateMethods.put(targetParameterType, handlerMethod);
            } else {
                if (fallbackMethods.containsKey(targetParameterType)) {
                    // we need to check for duplicate type matches,
                    // but only if we end up falling back
                    // and we'll only keep track of the first one
                    ambiguousFallbackType.compareAndSet(null, targetParameterType);
                }
                fallbackMethods.put(targetParameterType, handlerMethod);
            }
        }
    }, methodFilter);
    if (!candidateMethods.isEmpty()) {
        return candidateMethods;
    }
    if ((fallbackMethods.isEmpty() || ambiguousFallbackType.get() != null)
            && ServiceActivator.class.equals(annotationType)) {
        // a Service Activator can fallback to either MessageHandler.handleMessage(m) or RequestReplyExchanger.exchange(m)
        List<Method> frameworkMethods = new ArrayList<Method>();
        Class<?>[] allInterfaces = org.springframework.util.ClassUtils.getAllInterfacesForClass(targetClass);
        for (Class<?> iface : allInterfaces) {
            try {
                if ("org.springframework.integration.gateway.RequestReplyExchanger".equals(iface.getName())) {
                    frameworkMethods.add(targetClass.getMethod("exchange", Message.class));
                } else if ("org.springframework.integration.core.MessageHandler".equals(iface.getName())
                        && !requiresReply) {
                    frameworkMethods.add(targetClass.getMethod("handleMessage", Message.class));
                }
            } catch (Exception e) {
                // should never happen (but would fall through to errors below)
            }
        }
        if (frameworkMethods.size() == 1) {
            HandlerMethod handlerMethod = new HandlerMethod(frameworkMethods.get(0), canProcessMessageList);
            return Collections.<Class<?>, HandlerMethod>singletonMap(Object.class, handlerMethod);
        }
    }
    Assert.notEmpty(fallbackMethods, "Target object of type [" + this.targetObject.getClass()
            + "] has no eligible methods for handling Messages.");
    Assert.isNull(ambiguousFallbackType.get(), "Found ambiguous parameter type [" + ambiguousFallbackType
            + "] for method match: " + fallbackMethods.values());
    return fallbackMethods;
}