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

Bug with Reakt Promise and WebSocket call #709

Closed
RichardHightower opened this issue May 3, 2016 · 0 comments
Closed

Bug with Reakt Promise and WebSocket call #709

RichardHightower opened this issue May 3, 2016 · 0 comments

Comments

@RichardHightower
Copy link
Member

RichardHightower commented May 3, 2016

Bug with Reakt Promise and WebSocket call.
This bug was masked when testing serviceBundle and websocket proxy in the same unit test.
Now we pulled this out so it is just a WebSocket proxy test.

BoonClient (used for websocket RPC proxy creation) was not handling the Promise case.

    /**
     * Create an async handler. Uses some generics reflection to see what the actual type is
     *
     * @param serviceInterface client interface
     * @param call             method call object
     * @param handler          handler that will handle the message
     * @param <T>              the class of hte client interface
     * @return the new handler
     */
    private <T> Callback createHandler(final Class<T> serviceInterface, final MethodCall call,
                                       final Callback handler) {

        final ClassMeta<T> clsMeta = ClassMeta.classMeta(serviceInterface);
        final MethodAccess method = clsMeta.method(call.name());

        Class<?> returnType = null;
        Class<?> compType = null;

        if (method.returnType() == Promise.class) {

            Type t0 = method.method().getGenericReturnType();
            if (t0 instanceof ParameterizedType) {
                ParameterizedType parameterizedType =((ParameterizedType) t0);
                Type type = ((parameterizedType != null ? parameterizedType.getActualTypeArguments().length : 0) > 0 ? (parameterizedType != null ? parameterizedType.getActualTypeArguments() : new Type[0])[0] : null);

                if (type instanceof ParameterizedType) {
                    returnType = (Class) ((ParameterizedType) type).getRawType();
                    final Type type1 = ((ParameterizedType) type).getActualTypeArguments()[0];

                    if (type1 instanceof Class) {
                        compType = (Class) type1;
                    }
                } else if (type instanceof Class) {
                    returnType = (Class<?>) type;
                }

            }
        } else {
            if (method.parameterTypes().length > 0) {
                Type[] genericParameterTypes = method.getGenericParameterTypes();
                ParameterizedType parameterizedType = genericParameterTypes.length > 0 ? (ParameterizedType) genericParameterTypes[0] : null;

                Type type = ((parameterizedType != null ? parameterizedType.getActualTypeArguments().length : 0) > 0 ? (parameterizedType != null ? parameterizedType.getActualTypeArguments() : new Type[0])[0] : null);

                if (type instanceof ParameterizedType) {
                    returnType = (Class) ((ParameterizedType) type).getRawType();
                    final Type type1 = ((ParameterizedType) type).getActualTypeArguments()[0];

                    if (type1 instanceof Class) {
                        compType = (Class) type1;
                    }
                } else if (type instanceof Class) {
                    returnType = (Class<?>) type;
                }

            }
        }
        final Class<?> actualReturnType = returnType;

        final Class<?> componentClass = compType;

        /** Create the return handler. */
        return new Callback<Object>() {
            @Override
            public void accept(Object event) {

                if (actualReturnType != null) {

                    if (componentClass != null && actualReturnType == List.class) {

                        try {
                            //noinspection unchecked
                            event = MapObjectConversion.convertListOfMapsToObjects(componentClass, (List) event);
                        } catch (Exception ex) {
                            if (event instanceof CharSequence) {
                                String errorMessage = event.toString();
                                if (errorMessage.startsWith("java.lang.IllegalState")) {
                                    handler.onError(new IllegalStateException(errorMessage));
                                    return;
                                } else {
                                    handler.onError(new IllegalStateException("Conversion error"));
                                    return;
                                }
                            } else {
                                handler.onError(new IllegalStateException("Conversion error"));
                                return;
                            }
                        }
                    } else {

                        event = Conversions.coerce(actualReturnType, event);
                    }
                    //noinspection unchecked
                    handler.accept(event);
                }


            }

            @Override
            public void onError(Throwable error) {
                handler.onError(error);
            }

            @Override
            public void onTimeout() {
                handler.onTimeout();
            }
        };


    }

A few things I noticed about BoonClient while I was in there.
It always expects the callback to be the first argument.
(Callback probably should be the last but we have to maintain backwards compatibility, but we should fix this or document it.)

Now it handles promise returns fine.

The second thing that I noticed is that we only handle List/Collections not maps which is probably ok, but again should be changed or documented.

The third thing I noticed was that it uses ParameterizedType which works fine for Java and Scala but does not handle WildCar type which if I remember correctly Kotlin needs.

RichardHightower pushed a commit that referenced this issue May 3, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant