Como posso manter GWT de tentar incluir cada classe serializável quando eu uso ArrayList

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

  •  18-09-2019
  •  | 
  •  

Pergunta

Eu tenho um serviço RPC no GWT que precisa retornar uma lista. A lista pode ser preenchido com vários tipos de objetos, os quais são serializáveis ??e todos são mencionados no meu serviço para que eles devem estar disponíveis para GWT RPC. No entanto, a menos que eu colocar em um parâmetro de tipo genérico (por exemplo ArrayList<String>), GWT me dá o aviso:

Return type: java.util.ArrayList
    java.util.ArrayList
      Verifying instantiability
         java.util.ArrayList
            [WARN] Checking all subtypes of Object which qualify for serialization`
Adding '465' new generated units

Essencialmente, eu só quero uma maneira de declarar Lista ou ArrayList sem GWT tentando gerar código para cada objeto serializado no caminho de classe. não há alguma maneira de dizer GWT que eu sei o que estou fazendo e não enlouquecer?

Foi útil?

Solução

Deixe-me expandir sobre o que David Nouls disse. O compilador GWT não pode ler sua mente, então quando você deixar de especificar o que os tipos de retorno pode ser, GWT assume que pode ser qualquer coisa, e tem que fazer trabalho extra para se certificar de que pode acontecer no lado do cliente o Javascript.

Você realmente deve especificar que tipos são capazes de ser devolvido. Existe apenas de cabeça para fazer isso -. Como o compilador irá produzir um código mais otimizado, em vez de gerar código para lidar com '465 unidades genreated', então seus downloads será mais rápido

Gostaria de sugerir a criação de uma interface vazia chamada "BaseResult" e, em seguida, ter a objetos devolver tudo implementar essa interface.

/**
 * Marker interface 
 */
public interface BaseResult {
}

Em seguida, você especifica que o tipo de retorno do seu método rpc é ArrayList:

public interface MyRpcService extends RemoteService {
  public ArrayList<BaseResult> doRpc();
}

Em seguida, verifique se o seu retorno todos os objetos implementar essa interface.

public class UserInfo implements BaseResult {}
public class Order implements BaseResult {}

Agora, o compilador GWT terá um tempo muito mais fácil para otimizar seu código.

Outras dicas

É menos do que desejável ter as serializers tipo GWT compilador construir para tudo debaixo do sol; na pior das hipóteses, ele falhar inteiramente porque, por exemplo, pode haver uma classe (a partir Digamos que uma biblioteca GWT de terceiros que você está usando) que declara um tipo no pacote "cliente" que implementa java.io.Serializable . Se você tentar usar esse tipo em seu código, torna-se parte do classpath que o compilador GWT análises para construir uma serializer tipo para; no entanto, a tempo de execução a classe não é parte do classpath no servidor porque o tipo foi definido no pacote de "cliente" e, portanto, não compilado para o servidor! chamadas RPC, se tentar usar esse tipo específico ou não, falhar com uma exceção ClassNotFound. Perfeito!

É também, como o cartaz articulada, impossível fazer existente tipos primitivos implementar alguma interface de marcador seja IsSerializable ou uma interface de marcador personalizado (como BaseResult como sugerido acima).

No entanto, é necessária uma solução! Então aqui é o que eu vim com: 1) Use IsSerializable (ou alguma subclasse dela) ao invés de usar java.io.Serializable em todos os seus objetos de transferência de costume.

2) Utilize a seguinte implementação de RpcObject nos casos em que você precisa de um tipo de objeto genérico para conter um valor que você sabe que vai ser serializado GWT-RPC (quer se trate de uma das sua transferência objetos personalizados que implementos IsSerializable ou mais "primitivo" tipo, como java.lang.String [ver os comentários na implementação RpcObject abaixo para esses tipos que foram na lista de autorizações] que GWT já sabe como serializar!)

Esta solução está trabalhando para mim ... é tanto mantém GWT de construir-tipo serializers para cada classe java.io.Serializable sob o sol, enquanto, ao mesmo tempo me permite que o desenvolvedor para valores de transferência em torno de usar um único / tipo de uniforme para primitivas (que eu não posso adicionar a interface marcador IsSerializable a), bem como o meu próprio personalizados transferência IsSerializable objetos. Aqui está um exemplo do uso RpcObject (embora a usá-lo é tão simples, eu me sinto um pouco estranho sobre a inclusão de tais exemplos):

RpcObject rpcObject = new RpcObject();
rpcObject.setValue("This is a test string");

Graças ao java-genéricos truques do método getValue (), a carcaça pode ser reduzido ao mínimo, de modo a recuperar o valor (seja no cliente ou no servidor), você pode simplesmente fazer o seguinte sem qualquer necessidade de um elenco:

String value = rpcObject.getValue();

Você pode facilmente transferir um de seu costume tipo IsSerializable:

CustomDTO customDto= new CustomDTO(); // CustomDTO implements IsSerializable
customDto.setYourProperty(to_some_value);
RpcObject rpcObject = new RpcObject();
rpcObject.setValue(customDto);

E, novamente, mais tarde, o cliente ou servidor, o valor pode ser obtida facilmente (sem seleção de elenco):

CustomDTO customDto = rpcObject.getValue();

Você pode facilmente envolver algo como java.util.ArrayList:

List list = new ArrayList();  // Notice: no generics parameterization needed!
list.add("This is a string");
list.add(10);
list.add(new CustomDTO());

RpcObject rpcObject = new RpcObject();
rpcObject.setValue(list);

E mais uma vez, no final o cliente ou o código do servidor, você pode obter de volta a lista com:

List list = rpcObject.getValue();

Depois de olhar para o "white-listing" em RpcObject, você pode estar inclinado a pensar que única List<String> teria sido branco cotada; você seria errado ;-) Enquanto todos os valores adicionados ao List são IsSerializable ou objetos de tipos do JRE que GWT-RPC só sabe como serializar, então você vai estar tudo pronto . No entanto, se você precisa-lista branca tipos adicionais, por exemplo, um tipo de uma biblioteca de terceiros que usado java.io.Serializable vez de IsSerializable pode precisar de ser individualmente branco-listados (ver a implementação de RpcObject para mais detalhes) , eles podem ser adicionados como novos campos diretamente em RpcObject, ou para manter a sobrecarga menor nos casos comuns, adicioná-los a uma subclasse de RpcObject e usar a subclasse somente quando necessário (já que é uma subclasse, nenhum de seu cliente ou servidor método de assinaturas seria necessário para a mudança de usar o tipo RpcObject genérico).

Eu estou usando essa estratégia para resolver problemas quase idênticos aos descritos pelo seu autor. eu espero queoutro pode achar que é uma técnica útil, bem como, mas como sempre, sua milhagem pode variar ... Se a escola de pensamento GWT avançou além desta técnica, por favor comentário e deixe-me saber!

-Jeff

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.gwt.user.client.rpc.IsSerializable;

public class RpcObject implements IsSerializable {
    protected HashMap<String, IsSerializable> rpcObjectWrapper = new HashMap<String, IsSerializable>();

    /*
     * NOTE: The following fields are here to
     * trick/fool/work-around/whatever-you-want-to-call-it GWT-RPC's
     * serialization policy. Having these types present, even though their
     * corresponding fields are never used directly, enables GWT-RPC to
     * serialize/deserialize these primitive types if they are encountered in
     * the rpcWrapperObject! Of course GWT-RPC already knows how to serialize
     * all these primitive types, but since, for example, String doesn't
     * implement GWT's IsSerializable interface, GWT has no expectation that it
     * should ever be allowed in the rpcWrapperObject instance (and thus String,
     * as well as all the other Java primitives plus Arrays of such types as
     * well as List, Set, and Map, won't be part of the serialization policy of
     * the RpcObject type). This is unfortunate because thanks to java type
     * erasure, we can easily stuff Strings, Integers, etc into the wrapper
     * without any issues; however, GWT-RPC will cowardly refuse to serialize
     * them. Thankfully, it appears that the serialization policy is for the
     * RpcObject type as a whole rather than for the rpcObjectWrapper field
     * specifically. So, if we just add some dummy fields with these "primitive"
     * types they will get added to the serialization policy (they are
     * effectively white-listed) of the type as a whole, and alas, GWT-RPC stops
     * cowardly refusing to serialize them.
     */
    protected Byte _byte;
    protected Short _short;
    protected Integer _integer;
    protected Long _long;
    protected Float _float;
    protected Double _double;
    protected Date _date;
    protected Boolean _boolean;

    protected Byte[] _bytes;
    protected Short[] _shorts;
    protected Integer[] _integers;
    protected Long[] _longs;
    protected Float[] _floats;
    protected Double[] _doubles;
    protected Date[] _dates;
    protected Boolean[] _booleans;

    protected List<String> _list;
    protected Set<String> _set;
    protected Map<String, String> _map;

    public RpcObject() {
        super();
    }

    @SuppressWarnings("unchecked")
    public <X> X getValue() {
        HashMap h = (HashMap) rpcObjectWrapper;
        X value = (X) h.get("value");
        return value;
    }

    @SuppressWarnings("unchecked")
    public void setValue(Object value) {
        HashMap h = (HashMap) rpcObjectWrapper;
        h.put("value", value);
    }
}

Se você adicionar um ArrayList ou semelhante um campo Object a um objeto serializado, o compilador GWT não tem escolha, mas para incluir todas as variantes possíveis em sua compilação. Você é essencialmente declarando Posso enviar qualquer coisa usando este campo , para que o compilador garante que você é capaz de enviar qualquer coisa.

A solução é declarar, usando parâmetros genéricos, os tipos específicos que você está enviando. Isso pode exigir dividindo-se em vários parâmetros ou classes, mas ele faz manter o tamanho do código e compilação tempo para baixo.

Você terá que ajudar GWT por ser muito preciso no que você voltar. Uma solução típica é a utilização de uma classe de raiz ou interface de marcador e declarar que o método de RPC retorna um ArrayList, então GWT pode cortar para baixo os tipos possíveis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top