2008-09-26 6 views
35

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

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

ответ

12

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

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

будет приводить к ArrayList и Дата включения обоих в белый список.

Это становится сложнее, если вы пытаетесь использовать java.lang.Object вместо конкретных типов:

public Object getObjectForString(String str); 

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

7

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

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

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

+11

Он должен быть добавлен - класс также должен иметь открытый конструктор no-args по умолчанию. Просто реализовать интерфейс IsSerializable без этого недостаточно. Нашел это из-за трудного пути после часа отладки :) – 2010-08-30 05:09:46

+2

@AdrianPetrescu Это не совсем правильно. Конструктор no args может быть закрытым, но он должен быть тем не менее. Кроме того, сам класс не должен быть закрытым, и если он является внутренним классом, он должен быть статическим. И класс может не иметь конечных нестатических полей. – FrankPl 2014-03-27 15:55:46

29

Обходной путь: определить новый класс 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; 
} 
2

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

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

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

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

+1

И это работает без добавления этого типа в интерфейс RPC? – 2009-10-21 00:44:22

1

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

0

Для тех, кто будет иметь один и тот же вопрос и не находит предыдущие ответы удовлетворительных ...

Я использую GWT с GWTController, поскольку я использую Spring, который я модифицированную, как описано in this message. В сообщении объясняется, как изменить 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; 
} 
} 
1

Белый список генерируется GWT компилятором и содержит все элементы, которые определены в интерфейсе маркера IsSerializable.

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

- Андрей

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

0

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

Мне было проще создать класс, полученный из одного из типов, уже используемых в сервисном интерфейсе, и вставить его в клиентский пакет. Больше ничего не нужно.

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

Я имел эту проблему, но в конечном итоге обнаружения проблемы назад к строке кода в моем сериализуемого объекта:

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 = [email protected] 
    at com.google.gwt.user.server.rpc.impl.ServerSerializationStreamWriter.serialize(ServerSerializationStreamWriter.java:619) 
Смежные вопросы