Trivial GWT Example

Thursday, June 01, 2006 by Robert Hanson. «Permalink»

Editor's note 5/24/07: As you probably know, Adam and I just finished writing GWT in Action, a Manning title. Last week we were asked two pick two chapters that would be released for free. One of those, chapter 10, covers the GWT-RPC mechanism in some detail. Seeing that this entry is the most popular on the site, that was probably a good choice. So read the entry first, and if you still need to know more, go download chapter 10 from the GWT in Action book page. As always, feedback is welcome.

I was asked for a trivial RPC example for GWT by Plasante, and here it is.

File Structure

  1. ./org/hanson/gwt/MyApplication.gwt.xml  
  2. ./org/hanson/gwt/public/MyApplication.html  
  3. ./org/hanson/gwt/client/  
  4. ./org/hanson/gwt/client/  
  5. ./org/hanson/gwt/client/  
  6. ./org/hanson/gwt/server/  

At the root of the project is MyApplication.gwt.xml, which is the config file that defines any GWT project. I don't want to get into what each tag is used for, as I leave that to the GWT documentation. I do want to point out though that we defined a <servlet>, which is the server-side class for our RPC service.

  1. <module>  
  2.     <inherits name=''/>  
  3.     <entry-point class='org.hanson.gwt.client.MyApplication'/>  
  4.     <servlet path="/myService" class="org.hanson.gwt.server.MyServiceImpl"/>  
  5. </module>  

Under the public folder is the HTML file that will be used primarily for testing in "hosted" mode. This is a special mode used for testing GWT applications.

  1. <html>  
  2.   <head>  
  3.     <title>Wrapper HTML for MyApplication</title>  
  4.     <meta name='gwt:module' content='org.hanson.gwt.MyApplication' />  
  5.   </head>  
  6.   <body>  
  7.     <script language="javascript" src="gwt.js"></script>  
  8.   </body>  
  9. </html>  

The three files in the "client" package are the files that are converted to JavaScript by GWT. This is the default place to put these files, but you can configure a different package to hold these.

The first file is our "main" application that is executed when the HTML page loads the JavaScript file, and the other two are interfaces (stubs) to the remote code.

Lets look at the interfaces first. The first one, which we called MyService is the interface that is implemented by the server-side code. This is a sample, so I created a very simple interface with only a single method.

  1. // ./org/hanson/gwt/client/  
  3. package org.hanson.gwt.client;  
  5. import;  
  7. public interface MyService extends RemoteService  
  8. {  
  9.     public String myMethod (String s);  
  10. }  

The second interface is used for the client-side code. The name of the interface MUST be the same as the server-side interface with "Async" appended. It must implement all of the methods in the server-side interface, but all of the methods MUST also take an additional parameter, which is an AsyncCallback object.

  1. // ./org/hanson/gwt/client/  
  3. package org.hanson.gwt.client;  
  5. import;  
  7. public interface MyServiceAsync  
  8. {  
  9.     public void myMethod(String s, AsyncCallback callback);  
  10. }  

Notice that both interfaces are idential except for that additional parameter, and return type. I have highlighted that second part because I usually just copy the code from the first interface to the second, and it is easy to miss this small point.

Now, this is how you use it from the client application. First you create an AsyncCallback object by using the GWT.create() method. Note that this method takes the server-side interface as an argument, and will return an object that uses the client-side interface.

The object returned from the create() call also implements the ServiceDefTarget interface. We cast it to this interface, and set the serviceEntryPoint, which is the URL of the server-side code. We defined this location in the project configuration file with the <servler> tag.

Next we need to create an object instance that implements the AsyncCallback interface. Here we create an anonymous class for this. Calling server-side code happens asynchronously, meaning the code won't wait for a response (i.e. block). That is why we need to create this object. This object will handle the result when it makes it's way back fo the browser. We need to write code to handle both success and error conditions.

The last step is to actually call the server-side code. We do this by using the MyServiceAsync instance that we created, passing it our argument(s) as well as the AsyncCallback object to handle the result.

  1. // ./org/hanson/gwt/client/  
  3. package org.hanson.gwt.client;  
  5. import;  
  6. import;  
  7. import;  
  8. import;  
  9. import;  
  10. import;  
  12. /** 
  13. * Entry point classes define <CODE>onModuleLoad()</CODE>. 
  14. */  
  15. public class MyApplication implements EntryPoint  
  16. {  
  18.     public void onModuleLoad ()  
  19.     {  
  20.         // define the service you want to call  
  21.         MyServiceAsync svc = (MyServiceAsync) GWT.create(MyService.class);  
  22.         ServiceDefTarget endpoint = (ServiceDefTarget) svc;  
  23.         endpoint.setServiceEntryPoint("/myService");  
  25.         // define a handler for what to do when the  
  26.         // service returns a result  
  27.         AsyncCallback callback = new AsyncCallback()  
  28.         {  
  29.             public void onSuccess (Object result)  
  30.             {  
  31.                 RootPanel.get().add(new HTML(result.toString()));  
  32.             }  
  34.             public void onFailure (Throwable ex)  
  35.             {  
  36.                 RootPanel.get().add(new HTML(ex.toString()));  
  37.             }  
  38.         };  
  40.         // execute the service  
  41.         svc.myMethod("Do Stuff", callback);  
  42.     }  
  43. }  

Here is what the server-side code looks like. It just returns a simple String. The two things that are important to note is that the code does NOT live in the "client" package. It can not live there, the "client" package is for client-side only code.

We can use these classes on the server-side though. The difference is that we are actually using the Java versions, not the JavaScript versions of these classes and interfaces. In face we MUST implement the server-side interface, but becuase this interface is references in client-side code it MUST be in the "client" package.

Confusing? I hope not. Here is the short version:

  1. Server side code can go anywhere.
  2. Client side code must be in the "client" package (or sub-package).
  3. All code in the "client" package must be able to be converted to javaScript

  1. // ./org/hanson/gwt/server/  
  3. package org.hanson.gwt.server;  
  5. import org.hanson.gwt.client.MyService;  
  6. import;  
  8. public class MyServiceImpl extends RemoteServiceServlet implements MyService  
  9. {  
  10.     public String myMethod (String s)  
  11.     {  
  12.         return "You sent us '" + s + "'";  
  13.     }  
  14. }  

Posted by genius3k
하지만 실행해보면 아무 것도 안나오는 백지화면이었다.. 이거모 한건지 만건지..;;;;
이번에는 아무거나 몬가 뜨도록 만들어 보자

일단 사이트에 접속하여 아무 소스나 복사한 후 전에 만들었던 모듈에 붙여넣은 후 내 소스에 맞게 페키지명과 클래스명을 수정하였다.

그 다음은 실행~!!!

결과는 에러;;;;; 어쩌구 저쩌구 구구 절절하게도 써놨따;;  왜 에러 났는지 몰라서 구글링한 결과 gwt.xml파일을 수정안해서 그런것이 었다.

gwt.xml파일을 열어서
<!--  inherit GWT Ext --> 
    <inherits name='com.gwtext.GwtExt'/>
    <!--  GWT Ext stylesheet and script files --> 
    <stylesheet src='ext-2.0.2/resources/css/ext-all.css' /> 
    <script src="ext-2.0.2/adapter/ext/ext-base.js"/> 
    <script src="ext-2.0.2/ext-all.js"/>   
을 추가 시켜주었고
D:\solbox\test\build\classes\genius3k\public 폴더에 ext-2.0.2를 다운받아서 넣었다.

실행결과는 다음과 같다 ~~ 푸하하하..

아주 자알 자알된다 푸하하하
Posted by genius3k에 접속하여 plugin을 다운 받는다.
사이트에는 주소로 접속하여 파일을 다운 받고 압축을 풀어서 eclipse_home\plugins 안에 넣으라고 했지만 그리 해보니 설명과는 Eclise UI 구성도 틀리고 프로젝트 생성시 Configuration 항목에 Cypal Studio for GWT가 안보인다.;; 죈장;;;

그래서 전 버전인가 싶어 모든 다운로드 보기를 클릭한 후  다운받아서 해보니 Cypal 사이트의 설명과 동일한 UI가 나온다.

일단 GWT가 설치 되어있어야 하기 때문에 에가서 파일을 다운 받은 후 D:\googleGWT 폴더를 생성한 후 안에 압축을 풀었다.

이클립스를 실행한 후 Window->Preferences->Cypal Studio에 가서 GWT home 디렉토리를 D:\googleGWT로 설정했다.

새로운 프로젝트를 생성할 때 다음과 같이 Configuration에서 Cypal Studio for GWT 를 선택한 후 확인을 누르면 GWT-Ext기반의 프로젝트 생성이 완료된 것이다.

이제 모듈을 만들어서 추가해보고 런시켜 보자
File->New->Other->Cypal Studio-> GWT Module을 클릭하여 모듈을 생성한다

Run->Open Run Dialog를 클릭하여 Project와 Module을 선택하고 Run을 해보았다

결과는 에러.......
swt-win32-3235.dll이 파일이 없다는 에러였다 과연..D:\googleGWT에 가보니 없었다;;;;; 머 이래~~!!

분명 컴퓨터안에 그 파일이 있으리라는 생각으로 검색을 하니 eclipse\plugins 폴더 안에 있는 걸 발견~!!!
이 경로에 있는 걸로 봐서는 gwt plugin 설치시 자동으로 생성된듯 하다.
Window > Preferences > Cypal Studio에 가서 GWT Home설정을을 그 주소로 바꿔 보니 아주 깨끗하게 실행 되었다.

Posted by genius3k

Google Plugin은 Eclipse 3.3 이나 Eclipse 3.4를 지원한다.

1. Eclipse를 실행후 Help > Software Updates를 선택한 후 Available Software 탭을 선택한 한다.

2. Add Site 버튼을 클릭한후 이름을 대강 작성하고 URL 주소에 다음을 입력한다.  <-- Eclipse 버전 3.4일 경우  <-- Eclipse 버전 3.3일 경우
OK버튼 크릭 후 인스톨해주면 된다.

3. File > New 에 Web Application Project가 추가 되어있는 것을 볼 수 있다. 선택하여 새로운 프로젝트를 생성해보자.

4. 프로젝트 명과 페키지명을 입력 후 Run해주면 Google Web Toolkit Hosted Mode가 실행되는 것을 확인 할 수 있다.

Posted by genius3k

GWT 너는 누구냐~

GWT 2009.05.28 10:49

일단 간단하게 GWT를 이야기 하자면 Java로 코딩하면 결과가 최적화된 자바스크립트로 컴파일 된다는 것이다.

이 어찌 이리 신기할 수가 있나.. 얼마전에 샀던 그루비가 관심가져 달라고 울일이다. ㅋㅋㅋ 이미 GWT에 맘이 확가버렸다.

몇 가지 특징을 보면

1. Java 코드를 편집한 다음 다시 컴파일 하지 않고 변경내용을 즉시 볼수 있다. 즉 개발하는 동안 자바스크립트로의 컴파일하거나 서버에 배포할 필요 없이 호스트 모드 브라우저에서 새로고침 클릭한번으로 바로 볼수 있다

2.. Java 디버거를 사용하여 라이브 AJAX 코드를 단계별로 실행 할 수 있다. 이말인 Java와 동일한 디버그가 가능하다는 것. 즉 그 동안 Javascript를 디버그하기위해 여러 디버그툴을 써가며 잘 되지도 않는 디버그를 안해도 된다는 것이다

3. 최적화된 크로스브라우저 자바스크립트 파일로 컴파일된다.. 정말~!!???????

4. 아주 간단한 RPC를 통해 서버와 통신합니다.

5. 사용자 프로필을 기반으로 자바스크립트 스크립트 다운로드를 최적화

6. 브라우저의 뒤로 버튼과 기록을 간편하게 지원한다고 하니 Ajax로 처리된 페이지도 뒤로가기가 된다는 거 .. 정말~!!!??

7. JUnit으로 코드를 테스트 ㅋㅋㅋ
Posted by genius3k

티스토리 툴바