Как добавить тип в белый список политики сериализации GWT?

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

Вопрос

Сериализатор GWT имеет ограничения java.io.Serializable поддержка, но по соображениям безопасности существует белый список поддерживаемых типов.Документация, которую я нашел, например эта запись в часто задаваемых вопросах говорит, что любые типы, которые вы хотите сериализовать, «должны быть включены в белый список политики сериализации» и что список создается во время компиляции, но не объясняет, как компилятор решает, что попадает в белый список.

Сгенерированный список содержит ряд типов, которые являются частью стандартной библиотеки, например: java.lang.String и java.util.HashMap.Я получаю сообщение об ошибке при попытке сериализации java.sql.Date, который реализует Serializable интерфейс, но его нет в белом списке.Как добавить этот тип в список?

Это было полезно?

Решение

Любые конкретные типы, которые вы включаете в свой сервисный интерфейс, и любые типы, на которые они ссылаются, будут автоматически внесены в белый список, если они реализуют java.io.Serializable, например:

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

В результате оба ArrayList и Date будут включены в белый список.

Будет сложнее, если вы попытаетесь использовать java.lang.Object вместо определенных типов:

public Object getObjectForString(String str);

Потому что компилятор не знает, что внести в белый список.В том случае, если на объекты нет ссылок нигде в вашем сервисном интерфейсе, вам необходимо явно пометить их с помощью интерфейса IsSerializable, иначе он не позволит вам передать их через механизм 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 и содержит все записи, обозначенные интерфейсом маркера IsSerializable.

Чтобы добавить тип в список, вам просто нужно убедиться, что класс реализует интерфейс IsSerializable.

Кроме того, для корректной работы сериализации класс должен иметь конструктор по умолчанию без аргументов (при необходимости конструктор может быть закрытым).Также, если класс является внутренним, он должен быть помечен как статический.

ИМХО, самый простой способ программного доступа к белому списку — создать класс, подобный этому:

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

Затем включите его в .client пакет и ссылку из службы RPC (чтобы он анализировался компилятором).

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

Белый список создается компилятором gwt и содержит все записи, обозначенные интерфейсом маркера IsSerializable.

Чтобы добавить тип в список, вам просто нужно убедиться, что класс реализует интерфейс IsSerializable.

-- Андрей

Вероятно, это самое простое решение.Единственное, что следует помнить при этом, это то, что все классы, которые вы хотите сериализовать, должны иметь «открытый конструктор без аргументов» и (в зависимости от требований) методы установки для полей-членов.

для достижения желаемого результата удалите все war/<app>/gwt/*.gwt.rpc

Для всех, у кого возникнет тот же вопрос и предыдущие ответы не удовлетворят...

Я использую GWT с GWTController, так как использую Spring, который я изменил, как описано. в этом сообщении.В сообщении объясняется, как изменить 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