2012-02-10 3 views
2

클래스 (예 : 필드 추가/제거)에 대한 변경 사항과 함께 새 버전의 app이 배포 된 경우. 이전 버전을 실행중인 클라이언트는 com.google.gwt.user.client.rpc.SerializationException을 클라이언트 코드로 만든 RPC 과 함께 가져옵니다. 이는 예상되는 동작입니다. 결과적으로 클라이언트 측에서 IncompatibleRemoteServiceException이 발생합니다. 그러나 StatusCodeException이 발생합니다.직렬화 정책 변경시 GWT 클라이언트가 IncompatibleRemoteServiceException을 수신하지 않음

StatusCodeException은 500 오류이며 클라이언트 의 동작을 쉽게 사용자 지정할 수 없습니다. StatusCodeException 또는 500 오류가 새로운 버전이라고 가정하고 싶지는 않습니다. 여기서 무엇을 할 수 있습니까?

참고 : 이전 클라이언트의 serialization 정책이 새 서버에서 더 이상 유효하지 않기 때문에 서버 측 (로그)에서 분명히 SerializationExcepion을 얻습니다. 그래서 IncompatibleRemoteServiceException을 던지지 않는 이유는 무엇입니까?

감사합니다.

먼저 (이 서버 코드 기억, 모든 서비스 서블릿이 새로운 클래스에서 확장됩니다) RemoteServiceServlet 연장 :

답변

3

여기에 그 문제를 직면하고 내 솔루션입니다.

@Override 
protected SerializationPolicy doGetSerializationPolicy(
     HttpServletRequest request, String moduleBaseURL, String strongName) { 
    SerializationPolicy sp = super.doGetSerializationPolicy(request, 
            moduleBaseURL, strongName); 
    if(sp == null) { //no policy found, probably wrong client version 
     throw new InvalidPolicyException(); 
    } 
    return sp; 
} 

@Override 
protected void doUnexpectedFailure(Throwable e) { 
    if(e instanceof InvalidPolicyException) { 
     sendError(); //send message to reload client (wrong client version) 
     return; //that's it 
    } 
    super.doUnexpectedFailure(e); 
} 

sendError()는 기본적으로 GWT (500) 오류 코드에서 사용자 정의 사본입니다 개인 방법 (추한 구글 들여 쓰기 죄송합니다)

private void sendError() { 
    ServletContext servletContext = getServletContext(); 
    HttpServletResponse response = getThreadLocalResponse(); 
    try { 
      response.setContentType("text/plain"); 
      response.setStatus(HttpServletResponse.SC_CONFLICT); 
      try { 
      response.getOutputStream().write("wrong client version".getBytes("UTF-8")); 
      } catch (IllegalStateException e) { 
      // Handle the (unexpected) case where getWriter() was previously used 
      response.getWriter().write("wrong client version"); 
      } 
     } catch (IOException ex) { 
      servletContext.log(
       "sendError failed while sending the previous custom failure to the client", ex); 
     } 
} 
이 거기에 관련 코드

HttpServletResponse.SC_CONFLICT (409)을 사용했지만 아마도 영리한 오류 코드를 사용할 수 있습니다. 쓰여진 메시지는 정말로 중요하지 않습니다. 사용자 정의 RpcRequestBuilder에서 다음

(이것은 클라이언트 코드)

우리는 여러 팝업을 사용
public class CustomRequestBuilder extends RpcRequestBuilder { 

private class RequestCallbackWrapper implements RequestCallback { 

     private RequestCallback callback; 

     RequestCallbackWrapper(RequestCallback aCallback) { 
      this.callback = aCallback; 
     } 

     @Override 
     public void onResponseReceived(Request request, Response response) { 
      if(response.getStatusCode() == 409) { //wrong client version 
       Navigator.closeEveryPopUp(); 
       Navigator.showUncloseablePopUp("Login again!", 
           new ClickHandler() { 

        @Override 
        public void onClick(ClickEvent event) { 
         //reload your $#%^ client!!! 
         Window.Location.reload(); 
        } 
       }); 
      } else { 
       //(...)irrelevant security code here(...) 
       callback.onResponseReceived(request, response); 
      } 

     } 

     @Override 
     public void onError(Request request, Throwable exception) { 
      callback.onError(request, exception); 
     } 

} 

@Override 
protected void doFinish(RequestBuilder rb) { 
    //(...)more irrelevant security code here(...) 
    super.doFinish(rb); 
    rb.setCallback(new RequestCallbackWrapper(rb.getCallback())); 
} 
} 

, 즉 네비게이터 클래스에 대한 하나의 이유; 물론 사용자에게 경고하기 위해 자신의 스타일을 사용하십시오.

편집 : 여기서는 어떻게됩니까?

GWT RPC serializabled로 클래스를 표시하는 데 사용할 수있는 유일한 인터페이스는 GWT 1.3.3 IsSerializable입니다. 다음 버전은 동일한 목적을 위해 Java 표준 Serializable 인터페이스를 허용하지만이 인터페이스를 구현하는 객체에 대한 보안 정책 요구 사항을 추가합니다. 기본적으로 GWT는 고유 한 해시 이름을 사용하여 각 컴파일에 대한 정책을 생성합니다. Serializable으로 표시된 객체를 전송하려고 시도하는 이전 클라이언트는 클라이언트 측에서 일반적인 런타임 오류로 수신되는 직렬화 정책 예외를 서버 측에 던집니다. IsSerializable은 서명이 동일한 한 이전 클라이언트가 새 서비스를 계속 사용할 수있게합니다. 즉, 이 질문에 대한 또 다른 해결책은 GWT RPC를 통과하는 모든 객체를 IsSerializable으로 표시하는 것입니다. 그러나 어떤 이유로 GWT 인터페이스를 참조하지 않도록 객체를 필요로한다면, 이는 오래된 클라이언트 연결을위한 훌륭한 솔루션입니다.

1.3.3 대체에 대한 자세한 내용은 GWT's guide을 확인하십시오.

+0

이것은 GWT의 최신 버전 (예 : 2.5.1)에서는 문제가되지 않지만 GWT처럼 서비스 메소드에서 IncompatibleRemoteServiceException을 던져서 기능을 테스트 할 수 없다는 점에 유의하는 것이 유용합니다 StatusCodeException로 랩합니다. 그러나 실제로 클라이언트와 호환되지 않는 서비스를 실행하여 테스트하면 IncompatibleRemoteServiceException이 표시됩니다. – Shannon

관련 문제