GWT의 직렬화 정책 화이트리스트에 유형을 추가하려면 어떻게합니까?

StackOverflow https://stackoverflow.com/questions/138099

문제

GWT의 시리얼 라이저는 제한되어 있습니다 java.io.Serializable 지원이지만 보안상의 이유로 지원하는 유형의 화이트리스트가 있습니다. 예를 들어 내가 찾은 문서입니다 이 FAQ 항목 직렬화하려는 모든 유형은 "직렬화 정책 화이트리스트에 포함되어야하며"컴파일 타임에 목록이 생성되지만 컴파일러가 화이트리스트의 상황을 결정하는 방법을 설명하지 않는다고 말합니다.

생성 된 목록에는 표준 라이브러리의 일부인 여러 유형이 포함되어 있습니다. java.lang.String 그리고 java.util.HashMap. 직렬화를 시도 할 때 오류가 발생합니다 java.sql.Date, 그것을 구현합니다 Serializable 인터페이스이지만 화이트리스트에는 없습니다. 이 유형을 목록에 추가하려면 어떻게해야합니까?

도움이 되었습니까?

해결책

서비스 인터페이스에 포함하는 특정 유형과 참조하는 모든 유형이 Java.io.serializable을 구현하는 한 자동으로 화이트리스트로 표시됩니다.

public String getStringForDates(ArrayList<java.util.Date> dates);

ArrayList가 발생하고 날짜는 화이트리스트에 포함됩니다.

특정 유형 대신 java.lang.object를 사용하려고하면 까다로워집니다.

public Object getObjectForString(String str);

컴파일러는 화이트리스트에 무엇을 알지 못하기 때문입니다. 이 경우 서비스 인터페이스의 어느 곳에서나 객체를 참조하지 않으면 발행 가능한 인터페이스와 함께 명시 적으로 표시해야합니다. 그렇지 않으면 RPC 메커니즘을 통과 할 수 없습니다.

다른 팁

해결 방법이 있습니다 : 새로 정의하십시오 Dummy 직렬화에 포함하려는 모든 유형의 멤버 필드가있는 클래스. 그런 다음 RPC 인터페이스에 메소드를 추가하십시오.

Dummy dummy(Dummy d);

구현은 다음과 같습니다.

Dummy dummy(Dummy d) { return d; }

비동기 인터페이스에는 다음과 같습니다.

void dummy(Dummy d, AsyncCallback< Dummy> callback);

GWT 컴파일러가 이것을 선택하고 Dummy 클래스 참조 이러한 유형을 참조하면 흰색 목록에 포함됩니다.

예시 Dummy 수업:

public class Dummy implements IsSerializable {
    private java.sql.Date d;
}

화이트리스트는 GWT 컴파일러에 의해 생성되며 발행 가능한 마커 인터페이스로 지정된 모든 항목이 포함되어 있습니다.

목록에 유형을 추가하려면 클래스가 발행 가능한 인터페이스를 구현해야합니다.

또한 직렬화가 올바르게 작동하려면 클래스에 기본값이 없어야합니다 (필요한 경우 생성자가 비공개 일 수 있음). 또한 클래스가 내부 인 경우 정적으로 표시해야합니다.

프로그래밍 방식으로 화이트리스트에 액세스하는 가장 간단한 방법은 다음과 유사한 클래스를 만드는 것입니다.

public class SerializableWhitelist implements IsSerializable {
    String[] dummy1;
    SomeOtherThingsIWishToSerialize dummy2;
}

그런 다음 그것을 포함하십시오 .client RPC 서비스의 패키지 및 참조 (따라서 컴파일러가 분석합니다).

나는 더 일반적인 서비스를 만들기 위해 때때로 당신이 필요로하는 것입니다.

화이트리스트는 GWT 컴파일러에 의해 생성되며 발행 가능한 마커 인터페이스로 지정된 모든 항목이 포함되어 있습니다.

목록에 유형을 추가하려면 클래스가 발행 가능한 인터페이스를 구현해야합니다.

- Andrej

이것은 아마도 가장 쉬운 솔루션 일 것입니다. 이것으로 기억해야 할 유일한 것은 직렬화하려는 모든 클래스에 "공개, 무관"생성자 및 (요구 사항에 따라) 멤버 필드에 대한 세터 방법을 가져야한다는 것입니다.

원하는 결과가 모두 삭제되도록합니다 war/<app>/gwt/*.gwt.rpc

같은 질문을하고 이전 답변을 찾지 못하는 사람에게는 만족 스럽습니다 ...

GWTController와 함께 GWT를 사용하고 있습니다. 스프링을 사용하고 있기 때문에 설명대로 수정했습니다. 이 메시지에서. 이 메시지는 GrailsRemoteserViceservlet을 수정하는 방법을 설명하지만 GWTController는 같은 방식으로 rpc.decoderequest () 및 rpc.encoderesponseforsuccess ()를 호출합니다.

이것은 내가 사용하고있는 gwtcontroller의 최종 버전입니다.

/**
 * Used to instantiate GWT server in Spring context.
 *
 * Original version from <a href="http://docs.google.com/Doc?docid=dw2zgx2_25492p5qxfq&hl=en">this tutorial</a>.
 * 
 * ...fixed to work as explained <a href="http://blog.js-development.com/2009/09/gwt-meets-spring.html">in this tutorial</a>.
 * 
 * ...and then fixed to use StandardSerializationPolicy as explained in
 * <a href="http://markmail.org/message/k5j2vni6yzcokjsw">this message</a> to allow
 * using Serializable instead of IsSerializable in model.
 */
public class GWTController extends RemoteServiceServlet implements Controller, ServletContextAware {

 // Instance fields

 private RemoteService remoteService;

 private Class<? extends RemoteService> remoteServiceClass;

 private ServletContext servletContext;

 // Public methods

 /**
  * Call GWT's RemoteService doPost() method and return null.
  * 
  * @param request
  *            The current HTTP request
  * @param response
  *            The current HTTP response
  * @return A ModelAndView to render, or null if handled directly
  * @throws Exception
  *             In case of errors
  */
 public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
  doPost(request, response);
  return null; // response handled by GWT RPC over XmlHttpRequest
 }

 /**
  * Process the RPC request encoded into the payload string and return a string that encodes either the method return
  * or an exception thrown by it.
  * 
  * @param payload
  *            The RPC payload
  */
 public String processCall(String payload) throws SerializationException {
  try {
   RPCRequest rpcRequest = RPC.decodeRequest(payload, this.remoteServiceClass, this);

   // delegate work to the spring injected service
   return RPC.invokeAndEncodeResponse(this.remoteService, rpcRequest.getMethod(), rpcRequest.getParameters(), rpcRequest.getSerializationPolicy());
  } catch (IncompatibleRemoteServiceException e) {
   return RPC.encodeResponseForFailure(null, e);
  }
 }

 /**
  * Setter for Spring injection of the GWT RemoteService object.
  * 
  * @param RemoteService
  *            The GWT RemoteService implementation that will be delegated to by the {@code GWTController}.
  */
 public void setRemoteService(RemoteService remoteService) {
  this.remoteService = remoteService;
  this.remoteServiceClass = this.remoteService.getClass();
 }

 @Override
 public ServletContext getServletContext() {
  return servletContext;
 }

 public void setServletContext(ServletContext servletContext) {
  this.servletContext = servletContext;
 }
}

클라이언트 패키지에 넣거나 더미 서비스 인터페이스에 사용하는 것만으로는 시스템이 최적화 된 것처럼 보였기 때문에 충분하지 않다는 것을 알았습니다.

서비스 인터페이스에 이미 사용 된 유형 중 하나에서 파생 된 클래스를 작성하고 클라이언트 패키지에 고집하는 것이 가장 쉽다는 것을 알았습니다. 다른 것이 필요하지 않습니다.

public class GWTSerializableTypes extends SomeTypeInServiceInterface implements IsSerializable {
    Long l;
    Double d;
    private GWTSerializableTypes() {}
}

이 문제가 있었지만 직렬화 가능한 객체의 코드 라인으로 문제를 다시 추적했습니다.

Logger.getLogger(this.getClass().getCanonicalName()).log(Level.INFO, "Foo");

예외가 잡히기 전에 다른 불만은 없었습니다.

 @Override
  protected void serialize(Object instance, String typeSignature)
      throws SerializationException {
    assert (instance != null);

    Class<?> clazz = getClassForSerialization(instance);

    try {
      serializationPolicy.validateSerialize(clazz);
    } catch (SerializationException e) {
      throw new SerializationException(e.getMessage() + ": instance = " + instance);
    }
    serializeImpl(instance, clazz);
  }

스택 추적의 비즈니스 끝은 다음과 같습니다.

com.google.gwt.user.client.rpc.SerializationException: Type 'net.your.class' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = net.your.class@9c7edce
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top