Quando devo usar RequestFactory vs GWT-RPC?

87

Estou tentando descobrir se devo migrar minhas chamadas gwt-rpc para os novos cals RequestFactory GWT2.1.

A documentação do Google menciona vagamente que RequestFactory é um método de comunicação cliente-servidor melhor para "serviços orientados a dados"

O que posso extrair da documentação é que há uma nova classe Proxy que simplifica a comunicação (você não passa de um lado para outro a entidade real, mas apenas o proxy, por isso é mais leve e mais fácil de gerenciar)

Esse é todo o ponto ou estou perdendo algo mais no quadro geral?

Daghan ---
fonte
8
yay, esta questão está vinculada ao gwt devguide oficial !
törzsmókus

Respostas:

73

A grande diferença entre GWT RPC e RequestFactory é que o sistema RPC é "RPC por tipo concreto" enquanto RequestFactory é "RPC por interface".

O RPC é mais conveniente para começar, porque você escreve menos linhas de código e usa a mesma classe no cliente e no servidor. Você pode criar uma Personclasse com um monte de getters e setters e talvez alguma lógica de negócios simples para mais cortes e dados dos dados no Personobjeto. Isso funciona muito bem até que você queira ter um código específico do servidor e não compatível com o GWT dentro de sua classe. Como o sistema RPC é baseado em ter o mesmo tipo de concreto tanto no cliente quanto no servidor, você pode atingir uma parede de complexidade com base nos recursos de seu cliente GWT.

Para contornar o uso de código incompatível, muitos usuários acabam criando um par PersonDTOque obscurece o Personobjeto real usado no servidor. O PersonDTOapenas tem um subconjunto de getters e setters do lado do servidor, Personobjeto "domínio" . Agora você tem que escrever código que Marshalls dados entre o Persone PersonDTOobjeto e todos os outros tipos de objeto que você deseja passar para o cliente.

O RequestFactory começa assumindo que seus objetos de domínio não serão compatíveis com GWT. Você simplesmente declara as propriedades que devem ser lidas e gravadas pelo código do cliente em uma interface Proxy, e os componentes do servidor RequestFactory se encarregam de empacotar os dados e chamar seus métodos de serviço. Para aplicativos que têm um conceito bem definido de "Entidades" ou "Objetos com identidade e versão", o EntityProxytipo é usado para expor a semântica de identidade persistente de seus dados para o código do cliente. Objetos simples são mapeados usando o ValueProxytipo.

Com RequestFactory, você paga um custo inicial de inicialização para acomodar sistemas mais complicados do que o GWT RPC suporta facilmente. O RequestFactory ServiceLayerfornece significativamente mais ganchos para personalizar seu comportamento adicionando ServiceLayerDecoratorinstâncias.

BobV
fonte
Este é um bom motivo para apoiar minha decisão de mudar para RequestFactory. Obrigado, Bob! Faz sentido e eu não entendo porque algumas pessoas dizem "use RPC em alguns casos e RF em outros dependendo de suas necessidades" porque parece que com RPC você tem que escrever muito código de cola e aquela camada de DTO
Dan Leahu
5
Outra vantagem do RequestFactory é que pode ser usado com Android e GWT exatamente com o mesmo código.
Patrick
28

Passei por uma transição de RPC para RF. Em primeiro lugar, devo dizer que minha experiência é limitada, pois usei tantos EntityProxies quanto 0.

Vantagens do GWT RPC:

  • É muito fácil de configurar, entender e APRENDER!
  • Os mesmos objetos baseados em classe são usados ​​no cliente e no servidor.
  • Essa abordagem economiza toneladas de código.
  • Ideal, quando os mesmos objetos de modelo (e POJOS) são usados ​​no cliente e no servidor, POJOs == MODEL OBJECTs == DTOs
  • Fácil de mover coisas do servidor para o cliente.
  • Implementação de lógica comum fácil de compartilhar entre cliente e servidor (isso pode ser uma desvantagem crítica quando você precisa de uma lógica diferente).

Desvantagens do GWT RPC:

  • Impossível ter implementações diferentes de alguns métodos para servidor e cliente, por exemplo, você pode precisar usar uma estrutura de registro diferente no cliente e no servidor, ou um método igual diferente.
  • Implementação REALMENTE RUIM que não é mais extensível: a maior parte da funcionalidade do servidor é implementada como métodos estáticos em uma classe RPC. QUE REALMENTE SUGA.
  • por exemplo, é impossível adicionar ofuscação de erros do lado do servidor
  • Algumas questões de segurança XSS que não são resolvidas com elegância, consulte os documentos (não tenho certeza se isso é mais elegante para RequestFactory)

Desvantagens de RequestFactory:

  • MUITO DIFÍCIL de entender do doc oficial, qual é o mérito disso! Ele começa exatamente com o termo PROXIES completamente enganoso - estes são, na verdade, DTOs de RF que são criados por RF automaticamente. Os proxies são definidos por interfaces, por exemplo, @ProxyFor (Journal.class). O IDE verifica se existem métodos correspondentes no Diário. Tanto para o mapeamento.
  • RF não fará muito por você em termos de semelhanças de cliente e servidor porque
  • No cliente, você precisa converter "PROXIES" em seus objetos de domínio do cliente e vice-versa. Isso é completamente ridículo. Isso poderia ser feito em poucas linhas de código declarativamente, mas NÃO HÁ SUPORTE PARA ISSO! Se pudéssemos mapear nossos objetos de domínio para proxies com mais elegância, algo como o método JavaScript JSON.stringify (.. ,,) ESTÁ FALTANDO na caixa de ferramentas RF.
  • Não se esqueça de que você também é responsável por definir propriedades transferíveis de seus objetos de domínio para proxies e assim por diante recursivamente.
  • POOR ERROR HANDLING no servidor e - Stack-traces são omitidos por padrão no servidor e você está obtendo exceções inúteis vazias no cliente. Mesmo quando configurei o manipulador de erros personalizado, não consegui obter rastreamentos de pilha de baixo nível! Terrível.
  • Alguns pequenos bugs no suporte IDE e em outros lugares. Registrei duas solicitações de bug que foram aceitas. Nem um Einstein foi necessário para descobrir que aqueles eram realmente insetos.
  • A DOCUMENTAÇÃO SUGA. Como mencionei, os proxies deveriam ser melhor explicados, o termo é ENGANO. Para os problemas comuns básicos que eu estava resolvendo, o DOCS É INÚTIL. Outro exemplo de mal-entendido do DOC é a conexão das anotações JPA com RF. A partir dos documentos sucintos, parece que eles brincam juntos e, sim, há uma pergunta correspondente no StackOverflow. Eu recomendo esquecer qualquer 'conexão' JPA antes de entender RF.

Vantagens do RequestFactory

  • Excelente suporte do fórum.
  • O suporte IDE é muito bom (mas não é uma vantagem em comparação com RPC)
  • Flexibilidade de implementação de cliente e servidor (acoplamento fraco)
  • Coisas chiques, conectadas a EntityProxies, além de simples DTOs - cache, atualizações parciais, muito úteis para mobile.
  • Você pode usar ValueProxies como a substituição mais simples para DTOs (mas você mesmo deve fazer todas as conversões não tão sofisticadas).
  • Suporte para Bean Validations JSR-303.

Considerando outras desvantagens do GWT em geral:

  • Impossível executar testes de integração (código de cliente GWT + servidor remoto) com o suporte JUnit fornecido <= todo JSNI deve ser simulado (por exemplo, localStorage), SOP é um problema.

  • Sem suporte para configuração de teste - navegador sem interface + servidor remoto <= nenhum teste sem interface simples para GWT, SOP.

  • Sim, é possível executar testes de integração de selênio (mas não é isso que eu quero)

  • JSNI é muito poderoso, mas naquelas palestras brilhantes que dão em conferências, eles não falam muito sobre que escrever códigos JSNI tem algumas regras também. Novamente, descobrir como escrever um simples retorno de chamada foi uma tarefa digna de um verdadeiro pesquisador.

Em resumo, a transição do GWT RPC para o RequestFactory está longe de ser uma situação WIN-WIN, quando o RPC atende principalmente às suas necessidades. Você acaba gravando toneladas de conversões de objetos de domínio do cliente para proxies e vice-versa. Mas você obtém alguma flexibilidade e robustez de sua solução. E o suporte no fórum é excelente, no sábado também!

Considerando todas as vantagens e desvantagens que acabei de mencionar, vale a pena pensar com antecedência se alguma dessas abordagens realmente traz melhorias para sua solução e para sua configuração de desenvolvimento sem grandes compensações.

Honzajde
fonte
Check-out JBoss Erai. Adoro a abordagem deles ao RPC.
Καrτhικ
6

Acho a ideia de criar classes Proxy para todas as minhas entidades bastante irritante. Meus pojos Hibernate / JPA são gerados automaticamente a partir do modelo de banco de dados. Por que agora preciso criar um segundo espelho daqueles para RPC? Temos uma bela estrutura de "estivação" que se encarrega de "deshibernar" os pojos.

Além disso, a ideia de definir interfaces de serviço que não implementam totalmente o serviço do lado do servidor como um contrato java, mas implementam os métodos - soa muito J2EE 1.x / 2.x para mim.

Καrτhικ
fonte
5
É irritante, mas se você tiver que criar proxies de qualquer maneira, então você prefere ter a ajuda extra que o RF oferece para gerenciar esses proxies. Nem todo mundo quer enviar o pojo inteiro para o cliente - por exemplo, considere um jogo de pôquer - seu objeto Jogador pode ter informações que todos deveriam ver (número de cartas na mão, cartas mostrando a face, total de fichas) e outras informações que apenas um jogador deve ver (cartas viradas para baixo).
Peter Recore
Seu exemplo de pôquer é válido - nós contornamos isso tendo anotações (@WireTransient) que nossa estrutura de "estivation" usa para suprimir valores.
Καrτhικ
4

Ao contrário do RequestFactory, que tem recursos de teste e tratamento de erros pobres (uma vez que processa a maioria das coisas sob o capô do GWT), o RPC permite que você use uma abordagem mais orientada a serviços. RequestFactory implementa uma abordagem estilizada de injeção de dependência mais moderna que pode fornecer uma abordagem útil se você precisar invocar estruturas de dados polimórficas complexas. Ao usar RPC, suas estruturas de dados precisarão ser mais planas, pois isso permitirá que seus utilitários de empacotamento traduzam entre seus modelos json / xml e java. Usar o RPC também permite implementar uma arquitetura mais robusta, conforme citado na seção gwt dev no site do Google.

"Implementação Cliente / Servidor Simples

A primeira e mais direta maneira de pensar nas definições de serviço é tratá-las como todo o back-end do aplicativo. Dessa perspectiva, o código do lado do cliente é o seu "front end" e todo o código de serviço executado no servidor é o "back end". Se você adotar essa abordagem, suas implementações de serviço tendem a ser APIs de uso geral que não estão fortemente acopladas a um aplicativo específico. É provável que suas definições de serviço acessem diretamente bancos de dados por meio de JDBC ou Hibernate ou até mesmo arquivos no sistema de arquivos do servidor. Para muitos aplicativos, essa visualização é apropriada e pode ser muito eficiente porque reduz o número de camadas.

Implantação Multi-Tier

Em arquiteturas mais complexas e com várias camadas, suas definições de serviço GWT podem ser simplesmente gateways leves que chamam para ambientes de servidor de backend, como servidores J2EE. Dessa perspectiva, seus serviços podem ser vistos como a "metade do servidor" da interface de usuário do seu aplicativo. Em vez de serem de uso geral, os serviços são criados para as necessidades específicas de sua interface de usuário. Seus serviços se tornam o "front end" para as classes de "back end" que são escritas juntando chamadas para uma camada de serviços de backend de propósito geral, implementada, por exemplo, como um cluster de servidores J2EE. Esse tipo de arquitetura é apropriado se você precisar que seus serviços de back-end sejam executados em um computador fisicamente separado do servidor HTTP. "

Observe também que a configuração de um único serviço RequestFactory requer a criação de cerca de 6 classes java, enquanto o RPC requer apenas 3. Mais código == mais erros e complexidade em meu livro.

RequestFactory também tem um pouco mais de sobrecarga durante o processamento da solicitação, pois precisa organizar a serialização entre os proxies de dados e os modelos java reais. Essa interface adicionada adiciona ciclos de processamento extras que podem realmente ser adicionados em um ambiente corporativo ou de produção.

Também não acredito que os serviços RequestFactory sejam serialização como os serviços RPC.

Resumindo, depois de usar os dois por algum tempo, sempre uso o RPC, pois é mais leve, mais fácil de testar e depurar e mais rápido do que usar um RequestFactory. Embora RequestFactory possa ser mais elegante e extensível do que sua contraparte RPC. A complexidade adicional não o torna uma ferramenta melhor necessária.

Minha opinião é que a melhor arquitetura é usar dois aplicativos web, um cliente e um servidor. O servidor é um aplicativo da web java genérico simples e leve que usa a biblioteca servlet.jar. O cliente é GWT. Você faz uma solicitação RESTful via GWT-RPC no lado do servidor do aplicativo da Web do cliente. O lado do servidor do cliente é apenas uma passagem para o cliente Apache http, que usa um túnel persistente para o manipulador de solicitações que você está executando como um único servlet em seu aplicativo da web de servlet do servidor. O aplicativo da web de servlet deve conter sua camada de aplicativo de banco de dados (hibernate, cayenne, sql etc.). Isso permite que você divorcie totalmente os modelos de objeto de banco de dados do cliente real, proporcionando uma maneira muito mais extensível e robusta de desenvolver e testar a unidade de seu aplicativo. Concedido, requer um pouco de tempo de configuração inicial, mas, no final, permite que você crie uma fábrica de solicitações dinâmicas fora do GWT. Isso permite que você aproveite o melhor dos dois mundos. Sem mencionar ser capaz de testar e fazer alterações no lado do servidor sem ter que compilar ou construir o cliente gwt.

1-14x0r
fonte
0

Eu acho que é realmente útil se você tiver um pojo pesado no lado do cliente, por exemplo, se você usar entidades Hibernate ou JPA. Adotamos outra solução, usando um framework de persistência no estilo Django com entidades muito leves.

Uberto
fonte
0

A única ressalva que eu colocaria é que RequestFactory usa o transporte de dados binários (deRPC, talvez?) E não o GWT-RPC normal.

Isso só importa se você estiver fazendo testes pesados ​​com SyncProxy, Jmeter, Fiddler ou qualquer ferramenta semelhante que possa ler / avaliar o conteúdo da solicitação / resposta HTTP (como GWT-RPC), mas seria mais desafiador com deRPC ou RequestFactory.

Dhartford
fonte
1
Exceto que, na verdade, o RequestFactory fornece implementação "Java pura" pronta para uso, sem a necessidade de ferramentas de terceiros como SyncProxy. Consulte stackoverflow.com/questions/4853188/…
Thomas Broyer
0

Temos uma implementação muito grande do GWT-RPC em nosso projeto. Na verdade, temos 50 interfaces de serviço com muitos métodos cada, e temos problemas com o tamanho dos TypeSerializers gerados pelo compilador que tornam nosso código JS enorme. Portanto, estamos analisando para avançar em direção a RequestFactory. Eu tenho lido por alguns dias cavando na web e tentando descobrir o que outras pessoas estão fazendo. A desvantagem mais importante que vi, e talvez eu possa estar errado, é que com o RequestFactory você não está mais no controle da comunicação entre os objetos do Domínio do servidor e os do cliente. O que precisamos é aplicar o padrão carregar / salvar de forma controlada. Quer dizer, por exemplo o cliente recebe todo o grafo de objetos pertencentes a uma transação específica, faz suas atualizações e eles mandam tudo de volta para o servidor. O servidor será responsável por fazer a validação, comparar os valores antigos com os novos e fazer a persistência. Se 2 usuários de sites diferentes obtiverem a mesma transação e fizerem algumas atualizações, a transação resultante não deve ser a mesclada. Uma das atualizações deve falhar no meu cenário. Não vejo que RequestFactory ajude a suportar esse tipo de processamento.

Abraços Daniel

Daniel Ardison
fonte
Compartilho essas preocupações ... você acabou optando por RF?
HDave de
0

É justo dizer que, ao considerar um aplicativo MIS limitado, digamos com 10-20 objetos de negócios CRUD'able, e cada um com ~ 1-10 propriedades, isso realmente é uma questão de preferência pessoal que caminho seguir?

Em caso afirmativo, talvez projetar como seu aplicativo vai escalar pode ser a chave na escolha de sua rota GWT RPC ou RequestFactory:

  1. Espera-se que meu aplicativo permaneça com aquele número relativamente limitado de entidades, mas aumentará enormemente em termos de número. 10-20 objetos * 100.000 registros.

  2. Minha aplicação aumentará significativamente na amplitude de entidades, mas o número relativo de cada uma permanecerá baixo. 5000 objetos * 100 registros.

  3. Espera-se que meu aplicativo permaneça com aquele número relativamente limitado de entidades E permanecerá em um número relativamente baixo de, por exemplo, 10-20 objetos * 100 registros

No meu caso, estou no ponto de partida para tentar tomar essa decisão. Ainda mais complicado por ter que alterar a arquitetura do lado do cliente de UI, bem como fazer a escolha de transporte. Minha IU do GWT anterior (significativamente) em grande escala usava a biblioteca Hmvc4Gwt, que foi substituída pelos recursos do GWT MVP.

colher de sopa
fonte