use of com.kixeye.chassis.transport.dto.ServiceError in project chassis by Kixeye.
the class WebSocketTransportTest method testWebSocketServiceWithJsonWithWss.
@Test
public void testWebSocketServiceWithJsonWithWss() throws Exception {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("secureWebsocket.enabled", "true");
properties.put("secureWebsocket.port", "" + SocketUtils.findAvailableTcpPort());
properties.put("secureWebsocket.hostname", "localhost");
properties.put("secureWebsocket.selfSigned", "true");
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);
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setTrustAll(true);
WebSocketClient wsClient = new WebSocketClient(sslContextFactory);
try {
context.refresh();
final MessageSerDe serDe = context.getBean(JsonJacksonMessageSerDe.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("wss://localhost:" + properties.get("secureWebsocket.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();
}
}
}
use of com.kixeye.chassis.transport.dto.ServiceError 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);
}
}
}
}
use of com.kixeye.chassis.transport.dto.ServiceError 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.ServiceError in project chassis by Kixeye.
the class HttpExceptionHandler method defaultErrorHandler.
@ExceptionHandler(Exception.class)
@ResponseBody
public ServiceError defaultErrorHandler(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
ServiceError error = ExceptionServiceErrorMapper.mapException(ex);
switch(error.code) {
case ExceptionServiceErrorMapper.UNKNOWN_ERROR_CODE:
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
logger.error("Unexpected error", ex);
break;
case ExceptionServiceErrorMapper.VALIDATION_ERROR_CODE:
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
if (logger.isDebugEnabled()) {
logger.debug("Validation exception", ex);
}
break;
case ExceptionServiceErrorMapper.SECURITY_ERROR_CODE:
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
if (logger.isDebugEnabled()) {
logger.debug("Security exception", ex);
}
break;
default:
if (ex instanceof HttpServiceException) {
HttpServiceException httpEx = (HttpServiceException) ex;
response.setStatus(httpEx.httpResponseCode);
}
logger.warn("Service exception", ex);
break;
}
return error;
}
use of com.kixeye.chassis.transport.dto.ServiceError in project chassis by Kixeye.
the class ExceptionServiceErrorMapper method mapException.
/**
* Maps an exception to an error.
*
* @param ex
* @return
*/
public static ServiceError mapException(Throwable ex) {
ServiceError error = null;
if (ex instanceof ServiceException) {
ServiceException servEx = (ServiceException) ex;
error = servEx.error;
} else if (ex instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException validationEx = (MethodArgumentNotValidException) ex;
List<String> errors = Lists.newArrayList();
for (ObjectError objError : validationEx.getBindingResult().getAllErrors()) {
errors.add(objError.getObjectName() + ":" + objError.getCode() + ":" + objError.getDefaultMessage());
}
error = new ServiceError(VALIDATION_ERROR_CODE, Joiner.on("|").join(errors));
} else {
error = new ServiceError(UNKNOWN_ERROR_CODE, ex.getMessage());
}
return error;
}
Aggregations