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);
}
}
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));
}
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();
}
}
}
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);
}
}
}
}
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);
}
}
}
}
Aggregations