/* * Copyright (C) 2011 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.errai.bus.client.api.base; import static org.jboss.errai.bus.client.api.base.MessageBuilder.createConversation; import static org.jboss.errai.bus.client.api.base.MessageBuilder.createMessage; import org.jboss.errai.bus.client.ErraiBus; import org.jboss.errai.common.client.api.ErrorCallback; import org.jboss.errai.bus.client.api.messaging.Message; import org.jboss.errai.bus.client.api.builder.MessageBuildParms; import org.jboss.errai.common.client.protocols.MessageParts; /** * The default error callback implementation, used when {@link MessageBuildParms#defaultErrorHandling()} was invoked * (which is the default when there is no explicit mention of error handling to the MessageBuilder). * * @author Mike Brock * @author Christian Sadilek <csadilek@redhat.com> */ public class DefaultErrorCallback implements ErrorCallback<Message> { public static final DefaultErrorCallback INSTANCE = new DefaultErrorCallback(); public static final String CLIENT_ERROR_SUBJECT = "ClientBusErrors"; /** * Constructs an error message and puts it on the client message bus with the subject {@link #CLIENT_ERROR_SUBJECT}. * The error message is constructed with the following parts: * <dl> * <dt>Subject <dd>{@link #CLIENT_ERROR_SUBJECT} * <dt>ErrorMessage <dd>{@code e.getMessage()} if e != null; otherwise, {@code "Null exception reference"} * <dt>AdditionalDetails <dd>HTML marked-up stack trace of {@code e} if e != null; otherwise, {@code "No additional details"} * <dt>Throwable <dd>A marshalled representation of the exception object {@code e} if e != null; otherwise, this message part is omitted. * </dl> */ @Override public boolean error(Message message, final Throwable e) { try { if (e != null) { StringBuilder a = new StringBuilder("<br/>").append(e.getClass().getName()).append(": ").append(e.getMessage()).append("<br/>"); // Let's build-up the stacktrace. boolean first = true; for (StackTraceElement sel : e.getStackTrace()) { a.append(first ? "" : "  ").append(sel.toString()).append("<br/>"); first = false; } // And add the entire causal chain. Throwable t = e; while ((t = t.getCause()) != null) { first = true; a.append("Caused by:<br/>"); for (StackTraceElement sel : t.getStackTrace()) { a.append(first ? "" : "  ").append(sel.toString()).append("<br/>"); first = false; } } if (message == null) { createMessage(CLIENT_ERROR_SUBJECT) .with(MessageParts.ErrorMessage, e.getMessage()) .with(MessageParts.AdditionalDetails, a.toString()) .with(MessageParts.Throwable, e) .noErrorHandling().sendNowWith(ErraiBus.get()); } else { createConversation(message) .toSubject(CLIENT_ERROR_SUBJECT) .with(MessageParts.ErrorMessage, e.getMessage()) .with(MessageParts.AdditionalDetails, a.toString()) .with(MessageParts.Throwable, e) .noErrorHandling().reply(); } } else { if (message == null) { createMessage(CLIENT_ERROR_SUBJECT) .with(MessageParts.ErrorMessage, "Null exception reference") .with(MessageParts.AdditionalDetails, "No additional details") .noErrorHandling().sendNowWith(ErraiBus.get()); } else { createConversation(message) .toSubject(CLIENT_ERROR_SUBJECT) .with(MessageParts.ErrorMessage, "Null exception reference") .with(MessageParts.AdditionalDetails, "No additional details") .noErrorHandling().reply(); } } } catch (Throwable t) { t.printStackTrace(); throw new RuntimeException("could not dispatch wrapped exception to error handler", e); } return false; } }