Search in sources :

Example 1 with Envelope

use of com.kixeye.chassis.transport.dto.Envelope in project chassis by Kixeye.

the class ActionInvokingWebSocket method onWebSocketBinary.

public void onWebSocketBinary(byte[] payload, int offset, int length) {
    try {
        // don't accept empty frames
        if (payload == null || length < 1) {
            throw new WebSocketServiceException(new ServiceError("EMPTY_ENVELOPE", "Empty envelope!"), "UNKNOWN", null);
        }
        // check if we need to do psk encryption
        byte[] processedPayload = pskFrameProcessor.processIncoming(payload, offset, length);
        if (processedPayload != payload) {
            payload = processedPayload;
            offset = 0;
            length = payload.length;
        }
        // get the envelope
        final WebSocketEnvelope envelope = new WebSocketEnvelope(serDe.deserialize(payload, offset, length, Envelope.class));
        // gets all the actions
        Collection<WebSocketAction> actions = mappingRegistry.getActionMethods(envelope.getAction());
        final AtomicInteger invokedActions = new AtomicInteger(0);
        // invokes them
        for (final WebSocketAction action : actions) {
            // get and validate type ID
            Class<?> messageClass = null;
            if (StringUtils.isNotBlank(envelope.getTypeId())) {
                messageClass = messageRegistry.getClassByTypeId(envelope.getTypeId());
            }
            // validate if action has a payload class that it needs
            if (action.getPayloadClass() != null && messageClass == null) {
                throw new WebSocketServiceException(new ServiceError("INVALID_TYPE_ID", "Unknown type ID!"), envelope.getAction(), envelope.getTransactionId());
            }
            // invoke this action if allowed
            if (action.canInvoke(webSocketSession, messageClass)) {
                invokedActions.incrementAndGet();
                final Object handler = handlerCache.get(action.getHandlerClass().getName());
                final Class<?> finalMessageClass = messageClass;
                ListenableFuture<DeferredResult<?>> invocation = serviceExecutor.submit(new Callable<DeferredResult<?>>() {

                    @Override
                    public DeferredResult<?> call() throws Exception {
                        // then invoke
                        return action.invoke(handler, new RawWebSocketMessage<>(envelope.getPayload(), finalMessageClass, messageValidator, serDe), envelope, webSocketSession);
                    }
                });
                Futures.addCallback(invocation, new FutureCallback<DeferredResult<?>>() {

                    public void onSuccess(DeferredResult<?> result) {
                        if (result != null) {
                            result.setResultHandler(new DeferredResultHandler() {

                                @Override
                                public void handleResult(Object result) {
                                    if (result instanceof Exception) {
                                        onFailure((Exception) result);
                                        return;
                                    }
                                    sendResponse(result);
                                }
                            });
                        }
                    }

                    public void onFailure(Throwable t) {
                        if (t instanceof InvocationTargetException) {
                            t = ((InvocationTargetException) t).getTargetException();
                        }
                        ServiceError error = ExceptionServiceErrorMapper.mapException(t);
                        if (error != null && !ExceptionServiceErrorMapper.VALIDATION_ERROR_CODE.equals(error.code)) {
                            logger.error("Unexpected exception throw while executing action [{}]", envelope.getAction(), t);
                        }
                        sendResponse(error);
                    }

                    public Future<Void> sendResponse(Object response) {
                        try {
                            return sendMessage(envelope.getAction(), envelope.getTransactionId(), response);
                        } catch (IOException | GeneralSecurityException e) {
                            logger.error("Unable to send message to channel", e);
                            return Futures.immediateFuture(null);
                        }
                    }
                }, responseExecutor);
            }
        }
        // make sure we actually invoked something
        if (invokedActions.get() < 1) {
            throw new WebSocketServiceException(new ServiceError("INVALID_ACTION_MAPPING", "No actions invoked."), envelope.getAction(), envelope.getTransactionId());
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : ServiceError(com.kixeye.chassis.transport.dto.ServiceError) Envelope(com.kixeye.chassis.transport.dto.Envelope) GeneralSecurityException(java.security.GeneralSecurityException) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) InvocationTargetException(java.lang.reflect.InvocationTargetException) DeferredResultHandler(org.springframework.web.context.request.async.DeferredResult.DeferredResultHandler) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Future(java.util.concurrent.Future) DeferredResult(org.springframework.web.context.request.async.DeferredResult)

Example 2 with Envelope

use of com.kixeye.chassis.transport.dto.Envelope in project chassis by Kixeye.

the class ActionInvokingWebSocket method sendMessage.

/**
	 * Gets the websocket session.
	 * 
	 * @return
	 * @throws IOException 
	 * @throws GeneralSecurityException 
	 */
protected Future<Void> sendMessage(String action, String transactionId, String typeId, ByteBuffer payload) throws IOException, GeneralSecurityException {
    Envelope envelope = new Envelope(action, typeId, transactionId, payload);
    // generate blob
    byte[] envelopeBlob = serDe.serialize(envelope);
    // check if we need to do psk encryption
    envelopeBlob = pskFrameProcessor.processOutgoing(envelopeBlob, 0, envelopeBlob.length);
    return session.getRemote().sendBytesByFuture(ByteBuffer.wrap(envelopeBlob));
}
Also used : Envelope(com.kixeye.chassis.transport.dto.Envelope)

Example 3 with Envelope

use of com.kixeye.chassis.transport.dto.Envelope in project chassis by Kixeye.

the class HybridServiceTest method testHybridService.

@Test
public void testHybridService() throws Exception {
    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put("websocket.enabled", "true");
    properties.put("websocket.port", "" + SocketUtils.findAvailableTcpPort());
    properties.put("websocket.hostname", "localhost");
    properties.put("http.enabled", "true");
    properties.put("http.port", "" + SocketUtils.findAvailableTcpPort());
    properties.put("http.hostname", "localhost");
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    StandardEnvironment environment = new StandardEnvironment();
    environment.getPropertySources().addFirst(new MapPropertySource("default", properties));
    context.setEnvironment(environment);
    context.register(PropertySourcesPlaceholderConfigurer.class);
    context.register(TransportConfiguration.class);
    context.register(TestCombinedService.class);
    WebSocketClient wsClient = new WebSocketClient();
    RestTemplate httpClient = new RestTemplate();
    try {
        context.refresh();
        final MessageSerDe serDe = context.getBean(ProtobufMessageSerDe.class);
        final WebSocketMessageRegistry messageRegistry = context.getBean(WebSocketMessageRegistry.class);
        messageRegistry.registerType("stuff", TestObject.class);
        wsClient.start();
        httpClient.setInterceptors(Lists.newArrayList(LOGGING_INTERCEPTOR));
        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        for (MessageSerDe messageSerDe : context.getBeansOfType(MessageSerDe.class).values()) {
            messageConverters.add(new SerDeHttpMessageConverter(messageSerDe));
        }
        messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        httpClient.setMessageConverters(messageConverters);
        QueuingWebSocketListener webSocket = new QueuingWebSocketListener(serDe, messageRegistry, null);
        Session session = wsClient.connect(webSocket, new URI("ws://localhost:" + properties.get("websocket.port") + "/protobuf")).get(5000, TimeUnit.MILLISECONDS);
        Envelope envelope = new Envelope("getStuff", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        TestObject response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("stuff", response.value);
        byte[] rawStuff = serDe.serialize(new TestObject("more stuff"));
        envelope = new Envelope("setStuff", "stuff", null, ByteBuffer.wrap(rawStuff));
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("stuff", response.value);
        envelope = new Envelope("getStuff", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("more stuff", response.value);
        response = httpClient.getForObject(new URI("http://localhost:" + properties.get("http.port") + "/stuff/"), TestObject.class);
        Assert.assertNotNull(response);
        Assert.assertEquals("more stuff", response.value);
        response = httpClient.postForObject(new URI("http://localhost:" + properties.get("http.port") + "/stuff/"), new TestObject("even more stuff"), TestObject.class);
        Assert.assertNotNull(response);
        Assert.assertEquals("more stuff", response.value);
        response = httpClient.getForObject(new URI("http://localhost:" + properties.get("http.port") + "/stuff/"), TestObject.class);
        Assert.assertNotNull(response);
        Assert.assertEquals("even more stuff", response.value);
    } finally {
        try {
            wsClient.stop();
        } finally {
            context.close();
        }
    }
}
Also used : HashMap(java.util.HashMap) WebSocketMessageRegistry(com.kixeye.chassis.transport.websocket.WebSocketMessageRegistry) ArrayList(java.util.ArrayList) ProtobufMessageSerDe(com.kixeye.chassis.transport.serde.converter.ProtobufMessageSerDe) MessageSerDe(com.kixeye.chassis.transport.serde.MessageSerDe) WebSocketClient(org.eclipse.jetty.websocket.client.WebSocketClient) Envelope(com.kixeye.chassis.transport.dto.Envelope) AnnotationConfigWebApplicationContext(org.springframework.web.context.support.AnnotationConfigWebApplicationContext) URI(java.net.URI) StringHttpMessageConverter(org.springframework.http.converter.StringHttpMessageConverter) MapPropertySource(org.springframework.core.env.MapPropertySource) SerDeHttpMessageConverter(com.kixeye.chassis.transport.http.SerDeHttpMessageConverter) RestTemplate(org.springframework.web.client.RestTemplate) SerDeHttpMessageConverter(com.kixeye.chassis.transport.http.SerDeHttpMessageConverter) StringHttpMessageConverter(org.springframework.http.converter.StringHttpMessageConverter) HttpMessageConverter(org.springframework.http.converter.HttpMessageConverter) QueuingWebSocketListener(com.kixeye.chassis.transport.websocket.QueuingWebSocketListener) StandardEnvironment(org.springframework.core.env.StandardEnvironment) Session(org.eclipse.jetty.websocket.api.Session) Test(org.junit.Test)

Example 4 with Envelope

use of com.kixeye.chassis.transport.dto.Envelope in project chassis by Kixeye.

the class WebSocketTransportTest method testWebSocketServiceWithYaml.

@Test
public void testWebSocketServiceWithYaml() throws Exception {
    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put("websocket.enabled", "true");
    properties.put("websocket.port", "" + SocketUtils.findAvailableTcpPort());
    properties.put("websocket.hostname", "localhost");
    properties.put("http.enabled", "false");
    properties.put("http.port", "" + SocketUtils.findAvailableTcpPort());
    properties.put("http.hostname", "localhost");
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    StandardEnvironment environment = new StandardEnvironment();
    environment.getPropertySources().addFirst(new MapPropertySource("default", properties));
    context.setEnvironment(environment);
    context.register(PropertySourcesPlaceholderConfigurer.class);
    context.register(TransportConfiguration.class);
    context.register(TestWebSocketService.class);
    WebSocketClient wsClient = new WebSocketClient();
    try {
        context.refresh();
        final MessageSerDe serDe = context.getBean(YamlJacksonMessageSerDe.class);
        final WebSocketMessageRegistry messageRegistry = context.getBean(WebSocketMessageRegistry.class);
        messageRegistry.registerType("stuff", TestObject.class);
        wsClient.start();
        QueuingWebSocketListener webSocket = new QueuingWebSocketListener(serDe, messageRegistry, null);
        Session session = wsClient.connect(webSocket, new URI("ws://localhost:" + properties.get("websocket.port") + "/" + serDe.getMessageFormatName())).get(5000, TimeUnit.MILLISECONDS);
        Envelope envelope = new Envelope("getStuff", null, null, Lists.newArrayList(new Header("testheadername", Lists.newArrayList("testheaderval"))), null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        TestObject response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("stuff", response.value);
        byte[] rawStuff = serDe.serialize(new TestObject("more stuff"));
        envelope = new Envelope("setStuff", "stuff", null, ByteBuffer.wrap(rawStuff));
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("stuff", response.value);
        envelope = new Envelope("getStuff", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("more stuff", response.value);
        rawStuff = serDe.serialize(new TestObject(RandomStringUtils.randomAlphanumeric(100)));
        envelope = new Envelope("setStuff", "stuff", null, ByteBuffer.wrap(rawStuff));
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        ServiceError error = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(error);
        Assert.assertEquals(ExceptionServiceErrorMapper.VALIDATION_ERROR_CODE, error.code);
        envelope = new Envelope("expectedError", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        error = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(error);
        Assert.assertEquals(TestWebSocketService.EXPECTED_EXCEPTION.code, error.code);
        Assert.assertEquals(TestWebSocketService.EXPECTED_EXCEPTION.description, error.description);
        envelope = new Envelope("unexpectedError", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        error = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(error);
        Assert.assertEquals(ExceptionServiceErrorMapper.UNKNOWN_ERROR_CODE, error.code);
    } finally {
        try {
            wsClient.stop();
        } finally {
            context.close();
            while (context.isActive()) {
                Thread.sleep(100);
            }
        }
    }
}
Also used : ServiceError(com.kixeye.chassis.transport.dto.ServiceError) HashMap(java.util.HashMap) WebSocketMessageRegistry(com.kixeye.chassis.transport.websocket.WebSocketMessageRegistry) JsonJacksonMessageSerDe(com.kixeye.chassis.transport.serde.converter.JsonJacksonMessageSerDe) ProtobufMessageSerDe(com.kixeye.chassis.transport.serde.converter.ProtobufMessageSerDe) YamlJacksonMessageSerDe(com.kixeye.chassis.transport.serde.converter.YamlJacksonMessageSerDe) XmlMessageSerDe(com.kixeye.chassis.transport.serde.converter.XmlMessageSerDe) MessageSerDe(com.kixeye.chassis.transport.serde.MessageSerDe) WebSocketClient(org.eclipse.jetty.websocket.client.WebSocketClient) Envelope(com.kixeye.chassis.transport.dto.Envelope) AnnotationConfigWebApplicationContext(org.springframework.web.context.support.AnnotationConfigWebApplicationContext) URI(java.net.URI) Header(com.kixeye.chassis.transport.dto.Header) MapPropertySource(org.springframework.core.env.MapPropertySource) QueuingWebSocketListener(com.kixeye.chassis.transport.websocket.QueuingWebSocketListener) StandardEnvironment(org.springframework.core.env.StandardEnvironment) Session(org.eclipse.jetty.websocket.api.Session) WebSocketSession(org.eclipse.jetty.websocket.common.WebSocketSession) Test(org.junit.Test)

Example 5 with Envelope

use of com.kixeye.chassis.transport.dto.Envelope in project chassis by Kixeye.

the class WebSocketTransportTest method testWebSocketServiceWithXml.

@Test
public void testWebSocketServiceWithXml() throws Exception {
    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put("websocket.enabled", "true");
    properties.put("websocket.port", "" + SocketUtils.findAvailableTcpPort());
    properties.put("websocket.hostname", "localhost");
    properties.put("http.enabled", "false");
    properties.put("http.port", "" + SocketUtils.findAvailableTcpPort());
    properties.put("http.hostname", "localhost");
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    StandardEnvironment environment = new StandardEnvironment();
    environment.getPropertySources().addFirst(new MapPropertySource("default", properties));
    context.setEnvironment(environment);
    context.register(PropertySourcesPlaceholderConfigurer.class);
    context.register(TransportConfiguration.class);
    context.register(TestWebSocketService.class);
    WebSocketClient wsClient = new WebSocketClient();
    try {
        context.refresh();
        final MessageSerDe serDe = context.getBean(XmlMessageSerDe.class);
        final WebSocketMessageRegistry messageRegistry = context.getBean(WebSocketMessageRegistry.class);
        messageRegistry.registerType("stuff", TestObject.class);
        wsClient.start();
        QueuingWebSocketListener webSocket = new QueuingWebSocketListener(serDe, messageRegistry, null);
        Session session = wsClient.connect(webSocket, new URI("ws://localhost:" + properties.get("websocket.port") + "/" + serDe.getMessageFormatName())).get(5000, TimeUnit.MILLISECONDS);
        Envelope envelope = new Envelope("getStuff", null, null, Lists.newArrayList(new Header("testheadername", Lists.newArrayList("testheaderval"))), null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        TestObject response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("stuff", response.value);
        byte[] rawStuff = serDe.serialize(new TestObject("more stuff"));
        envelope = new Envelope("setStuff", "stuff", null, ByteBuffer.wrap(rawStuff));
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        response = webSocket.getResponse(5000, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("stuff", response.value);
        envelope = new Envelope("getStuff", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        response = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(response);
        Assert.assertEquals("more stuff", response.value);
        rawStuff = serDe.serialize(new TestObject(RandomStringUtils.randomAlphanumeric(100)));
        envelope = new Envelope("setStuff", "stuff", null, ByteBuffer.wrap(rawStuff));
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        ServiceError error = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(error);
        Assert.assertEquals(ExceptionServiceErrorMapper.VALIDATION_ERROR_CODE, error.code);
        envelope = new Envelope("expectedError", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        error = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(error);
        Assert.assertEquals(TestWebSocketService.EXPECTED_EXCEPTION.code, error.code);
        Assert.assertEquals(TestWebSocketService.EXPECTED_EXCEPTION.description, error.description);
        envelope = new Envelope("unexpectedError", null, null, null);
        session.getRemote().sendBytes(ByteBuffer.wrap(serDe.serialize(envelope)));
        error = webSocket.getResponse(5, TimeUnit.SECONDS);
        Assert.assertNotNull(error);
        Assert.assertEquals(ExceptionServiceErrorMapper.UNKNOWN_ERROR_CODE, error.code);
    } finally {
        try {
            wsClient.stop();
        } finally {
            context.close();
            while (context.isActive()) {
                Thread.sleep(100);
            }
        }
    }
}
Also used : ServiceError(com.kixeye.chassis.transport.dto.ServiceError) HashMap(java.util.HashMap) WebSocketMessageRegistry(com.kixeye.chassis.transport.websocket.WebSocketMessageRegistry) JsonJacksonMessageSerDe(com.kixeye.chassis.transport.serde.converter.JsonJacksonMessageSerDe) ProtobufMessageSerDe(com.kixeye.chassis.transport.serde.converter.ProtobufMessageSerDe) YamlJacksonMessageSerDe(com.kixeye.chassis.transport.serde.converter.YamlJacksonMessageSerDe) XmlMessageSerDe(com.kixeye.chassis.transport.serde.converter.XmlMessageSerDe) MessageSerDe(com.kixeye.chassis.transport.serde.MessageSerDe) WebSocketClient(org.eclipse.jetty.websocket.client.WebSocketClient) Envelope(com.kixeye.chassis.transport.dto.Envelope) AnnotationConfigWebApplicationContext(org.springframework.web.context.support.AnnotationConfigWebApplicationContext) URI(java.net.URI) Header(com.kixeye.chassis.transport.dto.Header) MapPropertySource(org.springframework.core.env.MapPropertySource) QueuingWebSocketListener(com.kixeye.chassis.transport.websocket.QueuingWebSocketListener) StandardEnvironment(org.springframework.core.env.StandardEnvironment) Session(org.eclipse.jetty.websocket.api.Session) WebSocketSession(org.eclipse.jetty.websocket.common.WebSocketSession) Test(org.junit.Test)

Aggregations

Envelope (com.kixeye.chassis.transport.dto.Envelope)16 Test (org.junit.Test)13 Header (com.kixeye.chassis.transport.dto.Header)10 ServiceError (com.kixeye.chassis.transport.dto.ServiceError)7 MessageSerDe (com.kixeye.chassis.transport.serde.MessageSerDe)7 ProtobufMessageSerDe (com.kixeye.chassis.transport.serde.converter.ProtobufMessageSerDe)7 QueuingWebSocketListener (com.kixeye.chassis.transport.websocket.QueuingWebSocketListener)7 WebSocketMessageRegistry (com.kixeye.chassis.transport.websocket.WebSocketMessageRegistry)7 URI (java.net.URI)7 HashMap (java.util.HashMap)7 Session (org.eclipse.jetty.websocket.api.Session)7 WebSocketClient (org.eclipse.jetty.websocket.client.WebSocketClient)7 MapPropertySource (org.springframework.core.env.MapPropertySource)7 StandardEnvironment (org.springframework.core.env.StandardEnvironment)7 AnnotationConfigWebApplicationContext (org.springframework.web.context.support.AnnotationConfigWebApplicationContext)7 JsonJacksonMessageSerDe (com.kixeye.chassis.transport.serde.converter.JsonJacksonMessageSerDe)6 XmlMessageSerDe (com.kixeye.chassis.transport.serde.converter.XmlMessageSerDe)6 YamlJacksonMessageSerDe (com.kixeye.chassis.transport.serde.converter.YamlJacksonMessageSerDe)6 WebSocketSession (org.eclipse.jetty.websocket.common.WebSocketSession)6 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)1