Статьи

Java исключения и Flex

Я видел несколько статей на эту тему, но я не нашел ни одной статьи, касающейся всех случаев (веб-сервисы, BlazeDS, BlazeDS и Spring, управление данными). Кроме того, подход от BlazeDS отличается от подхода, используемого интеграцией Spring / BlazeDS, и это может немного запутать новичка.

Предположим, что у вас есть слой сервисов, который должен вызываться из вашего приложения Flex. Мы можем представить эти сервисы как веб-сервисы или как удаленные методы. Или мы можем использовать управление данными. Методы java могут выдавать некоторые ошибки, и вы хотите отобразить их в приложении Flex.

Для простоты я возьму очень короткий метод. Подпись метода:

public String returnResults () создает исключение DatabaseDownException;

Ниже я напишу основные варианты использования:

а) Вы должны написать веб-сервис для возврата результата в виде XML. Что-то типа:

<?xml version="1.0" encoding="UTF-8"?>
<data>
<result>
</result>
</data>

В этом случае вам нужно будет улучшить ваш xml, добавив некоторые структуры для хранения сообщений об ошибках, например:

<?xml version="1.0" encoding="UTF-8"?>
<data>
<result>
</result>
<error>
</error>
</data>

При создании xml тело <error> будет заключено в сообщение об исключении. Конечно, можно добавить дополнительную информацию, такую ​​как тип исключения, серьезность и т. Д. Тот же подход следует использовать и при работе со службами SOAP.

б) вы планируете использовать BlazeDS и Java remoting

В этом случае все будет проще, BlazeDS может автоматически сериализовать выброшенное исключение, и вы можете найти сериализованное исключение в объекте FaultEvent. Давайте предположим, что у нас есть исключение Java, объявленное ниже. Он расширяет RuntimeException и имеет метод получения для настраиваемого поля.

public class DatabaseDownException extends RuntimeException{
private String customField;
public String getCustomField(){
return customField;
}
}

Код Flex объявляет удаленный объект и регистрирует обработчик (который также включен) для сбоя.

<mx:RemoteObject id="test" destination="testDestination" result="resultHandler(event)" fault="faultHandler(event)"/>
private function faultHandler(event:FaultEvent):void{
var exception:Object = event.fault.rootCause;
Alert.show(exception.cause);
Alert.show(exception.localizedMessage);
Alert.show(exception.message);
Alert.show(exception.customField);
}

В сериализованном исключении есть четыре поля. Первые три наследуются от объекта Throwable, последний объявлен в нашем исключении. Интересно отметить, что у вас не должно быть пары функций set / get для сериализации вашего свойства. Объект Throwable — единственный объект, для которого достаточно иметь методы get для сериализации значений (вы можете проверить это в flex.messaging.io.ThrowableProxy).

Единственным недостатком является то, что вы работаете с нетипизированными объектами … если вам это не нравится, вы можете вместо этого генерировать экземпляры flex.messaging.MessageException. Этот класс Java является частью BlazeDS и будет десериализован с использованием класса mx.messaging.messages.ErrorMessage (полученного из свойства event.message).

Вы можете добавить свои пользовательские данные в классе MessageException, используя расширенное свойство. Пример использования:

MessageException messageException = new MessageException();
HashMap<String,String> map = new HashMap<String,String>();
map.put("clientName", "JOHN");
map.put("clientSurname", "MASTER");
messageException.setExtendedData(map);
messageException.setCode("ACCOUNT_DISABLED");
throw messageException;

И на стороне Flex:

private function faultHandler(event:FaultEvent):void{
var errorMessage:ErrorMessage = event.message as ErrorMessage;
trace(errorMessage.extendedData.clientName);
trace(errorMessage.extendedData.clientSurname);
trace(errorMessage.faultCode);
}

Вероятно, вы не хотите иметь явную зависимость между вашим сервисным уровнем и библиотеками BlazeDS, и в этом случае вы должны построить поверх него делегат, который также будет выступать в качестве транслятора исключений.

в) Использование Spring BlazeDS Integration

У вас есть несколько преимуществ при использовании интеграции Spring BlazeDS, и если ваш средний уровень уже использует Spring, это обязательно. Преимущество, связанное с обработкой исключений, заключается в механизме транслятора исключений. Этот переводчик поймает все исключения, генерируемые сервисами, вызванными из Flex, и вы сможете перевести их в нечто более значимое для клиента.

Сначала нужно объявить переводчик исключений:

<bean id="exceptionTranslator" class="com.test.exception.ExceptionTranslatorImpl" />
<flex:message-broker services-config-path="/WEB-INF/flex/services-config.xml">
........
<flex:exception-translator ref="exceptionTranslator" />
</flex:message-broker>

Переводчик исключений находится ниже:

public class ExceptionTranslatorImpl implements ExceptionTranslator{
//handles all
public boolean handles(final Class<?> clazz){
return true;
}
public MessageException translate(final Throwable throwable){
if (throwable instanceof DatabaseDownException){
MessageException exception = new MessageException();
exception.setCode("FATAL_DB_DOWN");
return exception;
}
if ...........//check another things
}
}

Обратите внимание, что в текущей версии интеграции Spring / BlazeDS обязательно должен быть транслятор исключений, в противном случае исходная ошибка будет проглочена, и вы получите некоторую общую ошибку.

г) Использование управления данными

Тот же подход с точки с) применяется здесь. По сути, ваш ассемблер, который будет вызывать какой-либо сервис для получения / создания данных, позаботится о том, чтобы перевести исключения в нечто значимое для клиента. Я написал некоторое время об этом здесь .