gwt-rpc 호출을 새로운 GWT2.1 RequestFactory cals로 마이그레이션해야하는지 알아 내려고합니다.
Google 문서에서는 RequestFactory가 “데이터 지향 서비스”를위한 더 나은 클라이언트-서버 통신 방법이라고 모호하게 언급합니다.
문서에서 추출 할 수있는 것은 통신을 단순화하는 새로운 Proxy 클래스가 있다는 것입니다 (실제 엔티티를 앞뒤로 전달하지 않고 프록시 만 전달하므로 무게가 가볍고 관리하기 쉽습니다).
그게 요점입니까, 아니면 큰 그림에서 다른 것을 놓치고 있습니까?
답변
GWT RPC와 RequestFactory의 큰 차이점은 RPC 시스템은 “콘크리트 유형별 RPC”이고 RequestFactory는 “인터페이스 별 RPC”라는 것입니다.
RPC는 더 적은 수의 코드를 작성하고 클라이언트와 서버 모두에서 동일한 클래스를 사용하기 때문에 시작하기가 더 편리합니다. Person
getter와 setter가 많은 클래스를 만들 수 있으며 Person
개체 의 데이터를 추가 슬라이싱 및 다이 싱하기위한 간단한 비즈니스 논리를 만들 수 있습니다 . 이것은 클래스 내부에 서버 별, 비 GWT 호환 코드를 원할 때까지 매우 잘 작동합니다. RPC 시스템은 클라이언트와 서버 모두에서 동일한 구체적인 유형을 기반으로하기 때문에 GWT 클라이언트의 기능에 따라 복잡성 벽에 부딪 힐 수 있습니다.
호환되지 않는 코드의 사용을 피하기 위해 많은 사용자 가 서버에서 사용되는 PersonDTO
실제 Person
개체 를 숨기는 피어 를 만듭니다 . 는 PersonDTO
단지 서버 측의 getter 및 setter, “도메인”의 부분 집합이 Person
개체를. 이제 Person
및 PersonDTO
개체와 클라이언트에 전달하려는 다른 모든 개체 유형 간에 데이터를 마샬링하는 코드를 작성 해야합니다.
RequestFactory는 도메인 객체가 GWT와 호환되지 않는다고 가정하여 시작합니다. Proxy 인터페이스에서 클라이언트 코드가 읽고 써야하는 속성을 선언하기 만하면 RequestFactory 서버 구성 요소가 데이터 마샬링과 서비스 메서드 호출을 처리합니다. “엔티티”또는 “ID 및 버전이있는 객체”라는 잘 정의 된 개념이있는 애플리케이션의 경우 EntityProxy
유형은 데이터의 영구 ID 의미를 클라이언트 코드에 노출하는 데 사용됩니다. 단순 개체는 ValueProxy
유형을 사용하여 매핑됩니다 .
RequestFactory를 사용하면 GWT RPC가 쉽게 지원하는 것보다 더 복잡한 시스템을 수용하기 위해 초기 시작 비용을 지불합니다. RequestFactory ServiceLayer
는 ServiceLayerDecorator
인스턴스 를 추가하여 동작을 사용자 정의 할 수있는 훨씬 더 많은 후크를 제공 합니다.
답변
RPC에서 RF로 전환했습니다. 먼저 내 경험이 제한적이라고 말해야합니다. EntityProxies를 0만큼 많이 사용했습니다.
GWT RPC의 장점 :
- 설정, 이해 및 학습이 매우 쉽습니다!
- 클라이언트와 서버에서 동일한 클래스 기반 개체가 사용됩니다.
- 이 접근 방식은 많은 코드를 절약합니다.
- 클라이언트와 서버에서 동일한 모델 객체 (및 POJOS)가 사용되는 경우 POJO == MODEL OBJECTs == DTO
- 서버에서 클라이언트로 물건을 쉽게 옮길 수 있습니다.
- 클라이언트와 서버간에 공통 로직 구현을 쉽게 공유 할 수 있습니다 (다른 로직이 필요할 때 중요한 단점이 될 수 있음).
GWT RPC의 단점 :
- 서버와 클라이언트에 대해 다른 방법을 구현하는 것은 불가능합니다. 예를 들어 클라이언트와 서버에서 다른 로깅 프레임 워크를 사용하거나 다른 equals 방법을 사용해야 할 수 있습니다.
- 더 이상 확장 할 수없는 정말 나쁜 구현 : 대부분의 서버 기능은 RPC 클래스에서 정적 메서드로 구현됩니다. 정말 짜증나.
- 예 : 서버 측 오류 난독 화 추가 불가능
- 우아하게 해결할 수없는 일부 보안 XSS 문제는 문서를 참조하십시오 (RequestFactory에 대해 더 우아한 지 확실하지 않습니다).
RequestFactory의 단점 :
- 공식 문서에서 이해하기가 정말 어렵습니다. 그 장점은 무엇입니까! 그것은 완전히 오해의 소지가있는 용어 PROXIES에서 바로 시작합니다. 이것은 실제로 RF에 의해 자동으로 생성되는 RF의 DTO입니다. 프록시는 인터페이스에 의해 정의됩니다 (예 : @ProxyFor (Journal.class)). IDE는 저널에 해당 메서드가 있는지 확인합니다. 매핑을 위해 너무 많이.
- RF는 클라이언트와 서버의 공통성 측면에서 많은 일을하지 않습니다.
- 클라이언트에서 “PROXIES”를 클라이언트 도메인 개체로 또는 그 반대로 변환해야합니다. 이것은 완전히 우스꽝 스럽습니다. 몇 줄의 코드로 선언적으로 수행 할 수 있지만 이에 대한 지원은 없습니다! 도메인 객체를 프록시에 더 우아하게 매핑 할 수만 있다면 JavaScript 메소드 JSON.stringify (.. ,,)와 같은 것이 RF 도구 상자에서 MISSING입니다.
- 도메인 개체의 양도 가능한 속성을 프록시 등으로 설정하는 것도 재귀 적으로 담당한다는 사실을 잊지 마십시오.
- 서버에서 불량한 오류 처리 및-스택 추적은 기본적으로 서버에서 생략되고 클라이언트에서 쓸모없는 빈 예외가 발생합니다. 사용자 지정 오류 처리기를 설정해도 저수준 스택 추적에 도달 할 수 없었습니다! 무서운.
- IDE 지원 및 다른 곳의 사소한 버그. 나는 두 개의 버그 요청을 접수했습니다. 그것들이 실제로 버그라는 것을 알아 내기 위해 아인슈타인이 필요하지 않았습니다.
- 문서가 짜증나. 내가 언급했듯이 프록시는 더 잘 설명되어야하므로 용어는 잘못된 것입니다. 내가 해결하고 있던 기본적인 공통 문제에 대해서는 DOCS가 유용합니다. DOC에서 오해의 또 다른 예는 JPA 주석을 RF에 연결하는 것입니다. 간결한 문서에서 그들이 함께 플레이하는 것으로 보이며 예, StackOverflow에 해당하는 질문이 있습니다. RF를 이해하기 전에 JPA ‘연결’을 잊어 버리는 것이 좋습니다.
RequestFactory의 장점
- 우수한 포럼 지원.
- IDE 지원은 매우 우수합니다 (그러나 RPC와 달리 이점은 아님).
- 클라이언트 및 서버 구현의 유연성 (느슨한 결합)
- 단순한 DTO를 넘어 EntityProxies에 연결된 멋진 것들-캐싱, 부분 업데이트, 모바일에 매우 유용합니다.
- ValueProxies를 DTO의 가장 간단한 대체물로 사용할 수 있습니다 (하지만 모든 멋진 변환을 직접 수행해야하는 것은 아닙니다).
- Bean 유효성 검사 JSR-303 지원.
일반적으로 GWT의 다른 단점을 고려합니다.
-
제공된 JUnit 지원으로 통합 테스트 (GWT 클라이언트 코드 + 원격 서버)를 실행할 수 없습니다. <= 모든 JSNI가 모의 처리되어야합니다 (예 : localStorage). SOP가 문제입니다.
-
테스트 설정 지원 없음-헤드리스 브라우저 + 원격 서버 <= GWT, SOP에 대한 간단한 헤드리스 테스트 없음.
-
예, 셀레늄 통합 테스트를 실행할 수 있습니다 (하지만 제가 원하는 것은 아닙니다).
-
JSNI는 매우 강력하지만 회의에서 발표하는 반짝이는 강연에서는 JSNI 코드 작성에 몇 가지 규칙이 있다는 것에 대해 많이 이야기하지 않습니다. 다시 말하지만, 간단한 콜백을 작성하는 방법을 알아내는 것은 진정한 연구자의 가치가있는 작업이었습니다.
요약하면, GWT RPC에서 RequestFactory 로의 전환은 RPC가 대부분 사용자의 요구에 맞는 WIN-WIN 상황과는 거리가 멀습니다. 결국 클라이언트 도메인 개체에서 프록시로 또는 그 반대로 많은 변환을 작성합니다. 그러나 솔루션의 유연성과 견고성을 얻을 수 있습니다. 그리고 포럼에 대한 지원은 토요일에도 훌륭합니다!
방금 언급 한 모든 장단점을 고려할 때 이러한 접근 방식이 실제로 큰 절충없이 솔루션과 개발 설정을 개선 할 수 있는지 여부를 미리 생각하는 것이 좋습니다.
답변
모든 엔터티에 대한 프록시 클래스를 만드는 아이디어가 상당히 짜증납니다. 내 Hibernate / JPA pojos는 데이터베이스 모델에서 자동 생성됩니다. 이제 RPC 용으로 두 번째 미러를 만들어야하는 이유는 무엇입니까? 우리는 pojos의 “de-hibernating”을 처리하는 멋진 “estivation”프레임 워크를 가지고 있습니다.
또한 서버 측 서비스를 Java 계약으로 구현하지는 않지만 메소드를 구현하는 서비스 인터페이스를 정의한다는 아이디어는 J2EE 1.x / 2.x처럼 들립니다.
답변
오류 처리 및 테스트 기능이 부족한 RequestFactory (GWT의 내부에서 대부분의 작업을 처리하기 때문에)와 달리 RPC를 사용하면보다 서비스 지향적 인 접근 방식을 사용할 수 있습니다. RequestFactory는 복잡한 다형성 데이터 구조를 호출해야하는 경우 유용한 접근 방식을 제공 할 수있는보다 현대적인 종속성 주입 스타일 접근 방식을 구현합니다. RPC를 사용할 때는 마샬링 유틸리티가 json / xml과 Java 모델간에 변환 할 수 있도록 데이터 구조가 더 평평해야합니다. RPC를 사용하면 Google 웹 사이트의 gwt dev 섹션에서 인용 한 것처럼보다 강력한 아키텍처를 구현할 수도 있습니다.
“간단한 클라이언트 / 서버 배포
서비스 정의를 생각하는 가장 간단한 첫 번째 방법은이를 애플리케이션의 전체 백엔드로 취급하는 것입니다. 이러한 관점에서 클라이언트 측 코드는 “프런트 엔드”이고 서버에서 실행되는 모든 서비스 코드는 “백 엔드”입니다. 이 접근 방식을 취하면 서비스 구현은 하나의 특정 애플리케이션에 밀접하게 결합되지 않은보다 범용적인 API 인 경향이 있습니다. 서비스 정의는 JDBC 또는 Hibernate 또는 서버의 파일 시스템에있는 파일을 통해 데이터베이스에 직접 액세스 할 수 있습니다. 많은 응용 프로그램의 경우이보기가 적절하며 계층 수를 줄이므로 매우 효율적일 수 있습니다.
다중 계층 배포
보다 복잡한 다중 계층 아키텍처에서 GWT 서비스 정의는 J2EE 서버와 같은 백엔드 서버 환경을 호출하는 경량 게이트웨이 일 수 있습니다. 이러한 관점에서 서비스는 애플리케이션 사용자 인터페이스의 “서버 절반”으로 볼 수 있습니다. 일반 용도가 아닌 사용자 인터페이스의 특정 요구에 맞게 서비스가 생성됩니다. 서비스는 예를 들어 J2EE 서버의 클러스터로 구현 된보다 범용적인 백엔드 서비스 계층에 대한 호출을 함께 연결하여 작성된 “백엔드”클래스에 대한 “프론트 엔드”가됩니다. 이러한 종류의 아키텍처는 백엔드 서비스를 HTTP 서버와 물리적으로 분리 된 컴퓨터에서 실행해야하는 경우에 적합합니다. “
또한 단일 RequestFactory 서비스를 설정하려면 RPC에 3 개만 필요한 자바 클래스를 6 개 정도 만들어야합니다. 더 많은 코드 == 내 책에서 더 많은 오류와 복잡성이 발생합니다.
RequestFactory는 또한 데이터 프록시와 실제 Java 모델 간의 직렬화를 마샬링해야하므로 요청 처리 중에 약간 더 많은 오버 헤드가 있습니다. 이 추가 된 인터페이스는 엔터프라이즈 또는 프로덕션 환경에서 실제로 추가 될 수있는 추가 처리주기를 추가합니다.
또한 RequestFactory 서비스가 RPC 서비스와 같은 직렬화라고 생각하지 않습니다.
대체로 얼마 동안 두 가지를 모두 사용한 후에는 항상 RPC를 더 가볍고 테스트 및 디버깅하기 쉽고 RequestFactory를 사용하는 것보다 빠릅니다. RequestFactory는 RPC 카운터 부분보다 더 우아하고 확장 가능할 수 있습니다. 복잡성이 추가되었다고해서 더 나은 도구가 필요한 것은 아닙니다.
제 생각에는 최고의 아키텍처는 두 개의 웹 앱, 하나의 클라이언트와 하나의 서버를 사용하는 것입니다. 서버는 servlet.jar 라이브러리를 사용하는 간단한 경량의 일반 Java 웹 애플리케이션입니다. 클라이언트는 GWT입니다. GWT-RPC를 통해 클라이언트 웹 애플리케이션의 서버 측에 RESTful 요청을합니다. 클라이언트의 서버 측은 서버 서블릿 웹 애플리케이션에서 단일 서블릿으로 실행중인 요청 핸들러에 지속성 터널을 사용하는 http 클라이언트를 아파치하는 것입니다. 서블릿 웹 애플리케이션은 데이터베이스 애플리케이션 계층 (hibernate, cayenne, sql 등)을 포함해야합니다.이를 통해 실제 클라이언트에서 데이터베이스 개체 모델을 완전히 분리하여 애플리케이션을 개발하고 단위 테스트하는 훨씬 더 확장 가능하고 강력한 방법을 제공 할 수 있습니다. 초기 설정 시간이 약간 필요합니다. 하지만 결국 GWT 외부에있는 동적 요청 팩토리를 만들 수 있습니다. 이를 통해 두 세계의 장점을 모두 활용할 수 있습니다. gwt 클라이언트를 컴파일하거나 빌드하지 않고도 서버 측을 테스트하고 변경할 수 있다는 것은 말할 것도 없습니다.
답변
예를 들어 Hibernate 또는 JPA 엔티티를 사용하는 경우와 같이 클라이언트 측에 무거운 pojo가 있으면 정말 도움이된다고 생각합니다. 우리는 매우 가벼운 엔터티와 함께 Django 스타일 지속성 프레임 워크를 사용하는 또 다른 솔루션을 채택했습니다.
답변
내가 넣을 유일한 경고는 RequestFactory가 정상적인 GWT-RPC가 아닌 바이너리 데이터 전송 (deRPC 아마도?)을 사용한다는 것입니다.
이는 SyncProxy, Jmeter, Fiddler 또는 HTTP 요청 / 응답 (예 : GWT-RPC)의 내용을 읽고 평가할 수있는 유사한 도구로 무거운 테스트를 수행하는 경우에만 중요하지만 deRPC 또는 RequestFactory에서는 더 어려울 수 있습니다.
답변
우리는 프로젝트에서 GWT-RPC를 매우 많이 구현했습니다. 사실 우리는 각각 많은 메소드를 가진 50 개의 서비스 인터페이스를 가지고 있으며, 우리의 JS 코드를 엄청나게 만드는 컴파일러에 의해 생성 된 TypeSerializer의 크기에 문제가 있습니다. 그래서 우리는 RequestFactory로 이동하기 위해 분석하고 있습니다. 나는 며칠 동안 웹을 파헤 치고 다른 사람들이하는 일을 찾으려고하는 것을 읽었습니다. 내가 본 가장 중요한 단점은 RequestFactory를 사용하면 더 이상 서버 도메인 개체와 클라이언트 개체 간의 통신을 제어 할 수 없다는 것입니다. 우리에게 필요한 것은 제어 된 방식으로로드 / 저장 패턴을 적용하는 것입니다. 예를 들어 클라이언트는 특정 트랜잭션에 속하는 개체의 전체 개체 그래프를 수신하고 업데이트를 수행하고 전체를 서버로 다시 보냅니다. 서버는 유효성 검사를 수행하고 이전 값과 새 값을 비교하고 지속성을 수행합니다. 다른 사이트의 2 명의 사용자가 동일한 트랜잭션을 받고 일부 업데이트를 수행하는 경우 결과 트랜잭션이 병합되지 않아야합니다. 내 시나리오에서 업데이트 중 하나가 실패합니다. RequestFactory가 이런 종류의 처리를 지원하는 데 도움이되지는 않습니다.
감사합니다 Daniel