Как я могу добавить обработчик исключений на стороне сервера GWT? - PullRequest
0 голосов
/ 06 января 2019

Я хочу обернуть все исходящие исключения с сервера GWT (только сервер, ничего на клиенте):

public class AuthServiceImpl extends RemoteServiceServlet implements AuthService {
    public String loginAttemt(String username, String password) {
        AwesomeUser user = AwesomeUserDao.forUsername(username);
        if(BCrpyt.checkpw(user.getPasshash(), password)) {
            String code = magicallyGenerateErrorCode();
            logger.error("Invalid login attempt - error code"  + code);
            throw new AwesomeException("password", "Invalid username or password", code);
        }
    }
}

@RemoteServiceRelativePath("auth")
public interface AuthService extends RemoteService {
    String loginAttempt(String username, String password) throws AwesomeException;
}

public interface AuthServiceAsync {
    void loginAttempt(String username, String password, AsyncCallback<String> callback) throws AwesomeException;
}

Сейчас, прямо сейчас, это работает. На стороне клиента я просто делаю что-то вроде этого (getField(String) - это небольшая настройка, которую я сделал по несвязанным причинам, но она помогает понять смысл)

public void onFailure(Throwable caught) {
    if(caught instanceof AwesomeException) {
        AwesomeException a = (AwesomeException)caught;
        getField(a.getfield()).setErrorText(a.getText());
        getField("error-code").setText(a.getCode());
    }
}

И да, это работает как ожидалось. Но представьте на мгновение, что user было null - некоторые из вас, возможно, читали, что «О, боже, у него может быть NPE, если имя пользователя не существует», и вы абсолютно правы. И, конечно же, я защищаю такие вещи. Однако я не буду ловить все эти обстоятельства. Я хотел бы добавить где-нибудь обработчик исключений, который перехватывает все эти исключения и помещает их в AwesomeException - в частности, чтобы я мог передать соответствующий код ошибки пользователю, чтобы он мог связаться со службой поддержки по поводу того, что пошло не так. Я не хочу полагаться на то, что программист всегда помнит каждый возможный нулевой и недопустимый аргумент и все другие исключения времени выполнения. Конечно, я не хочу, чтобы они были довольны, но я хочу убедиться, что у пользователя ВСЕГДА есть код ошибки, с которым можно связаться в службу поддержки.

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

Я попытался отследить обратный вызов, но в итоге он теряется в классе RPC. Но, конечно, я не первый, кто пытается перехватить исключения GWT, посылаемые сервером, верно?

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Вместо службы, расширяющей RemoteServiceServlet, вы можете создать свой собственный сервлет и делегировать RemoteServiceServlet как:

public class GwtServiceServlet extends HttpServlet {
    public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException {
        Object delegate = ...;

        RemoteServiceServlet remoteServiceServlet = new RemoteServiceServlet(delegate);
        remoteServiceServlet.init(getServletConfig());
        remoteServiceServlet.doPost(request, response);
    }
}

Где delegate - реализация интерфейса службы. Поскольку вы контролируете создание реализации службы, теперь вы можете обернуть ее в прокси-сервер для преобразования исключений или ведения журнала.

0 голосов
/ 08 января 2019

Это может быть сделано путем расширения RemoteServiceServlet и обработки исключений, например, в processCall(RPCRequest rpcRequest) или doUnexpectedFailure(Throwable e).

например:.

Этот метод вызывается только для исключений или ошибок, которые не являются частью подписи метода обслуживания, или что результат от SecurityExceptions, SerializationExceptions или другие сбои в рамки RPC.

Это означает, что любой NPE и т. Д. Может быть сопоставлен с пользовательским исключением.

  protected void doUnexpectedFailure(Throwable e) {
    try {
      getThreadLocalResponse().reset();
    } catch (IllegalStateException ex) {
      /*
       * If we can't reset the request, the only way to signal that something
       * has gone wrong is to throw an exception from here. It should be the
       * case that we call the user's implementation code before emitting data
       * into the response, so the only time that gets tripped is if the object
       * serialization code blows up.
       */
      throw new RuntimeException("Unable to report failure", e);
    }
    ServletContext servletContext = getServletContext();

    String code = magicallyGenerateErrorCode();
    AwesomeException awesomeException = new AwesomeException("error", "Unexpected Error. Pls contact support", code);

    RPCServletUtils.writeResponseForUnexpectedFailure(servletContext,
        getThreadLocalResponse(), awesomeException);
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...