tag:blogger.com,1999:blog-77723853318607700622024-03-13T15:46:10.637-07:00Desarrollo en GWTJuan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.comBlogger14125tag:blogger.com,1999:blog-7772385331860770062.post-13556680591355864862013-08-22T10:27:00.002-07:002016-02-05T13:00:45.639-08:00Eclipse Kepler and Vaadin 7 - Visual Designer - Design Tab is missing<b>Workaround</b><br />
<a name='more'></a><br /><br />
I installed the Vaadin Plugin for Eclipse and I wanted to test the visual designer and there no was no design Tab.
I found a useful link.<br />
<br />
<a href="http://stackoverflow.com/questions/17994805/how-to-install-xulrunner-for-eclipse">http://stackoverflow.com/questions/17994805/how-to-install-xulrunner-for-eclipse</a><br />
<br />
1. Well I did the next.
Downloaded the latest XULRunner from mozilla<br />
<a href="http://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases/latest/runtimes/">http://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases/latest/runtimes/</a><br />
and extracted in some directory.<br />
<br />
2. Edit the eclipse.ini file and add this line<br />
<br />
-Dorg.eclipse.swt.browser.XULRunnerPath=D:\xulrunner<br />
<br />
3. When I start Eclipse Kepler I get a weird message<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxKleCZvr4wnMqQooKdF77HeqsKC_WGoIVmqVaPhSwYXhyphenhyphenB6bW_jTwm2DK4NtD1IFp1Ube52MOIZ0WNSY4DWBYbx2iYIOaV-C5daNi1ON5yDwjflWlKTZNmJ6YYrvPSw_90RNvUljVQmLU/s1600/eclipse-kepler-vaadin-plugin.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxKleCZvr4wnMqQooKdF77HeqsKC_WGoIVmqVaPhSwYXhyphenhyphenB6bW_jTwm2DK4NtD1IFp1Ube52MOIZ0WNSY4DWBYbx2iYIOaV-C5daNi1ON5yDwjflWlKTZNmJ6YYrvPSw_90RNvUljVQmLU/s320/eclipse-kepler-vaadin-plugin.png" width="320" /></a></div>
<br />
Now The Designer Tab is showing!<br />
<br />
<br />
<br />
<br />Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com5tag:blogger.com,1999:blog-7772385331860770062.post-36962142567589914272012-12-04T23:56:00.002-08:002016-02-05T11:51:26.481-08:00GWT and PHPThis time I will describe a CRUD application using GXT Grid and HttpProxy on the client side and on the server side I use PHP and PDO to access a PostgreSQL database.<br />
The communication between client and server side is using JSON then you can use whatever language on the server side that produce a JSON output.<br />
The source code is on github <a href="https://github.com/poseidonjm/GXT3-PHP">https://github.com/poseidonjm/GXT3-PHP</a> is structured using <a href="http://code.google.com/p/gwt-platform/">GWTP</a> and <a href="https://developers.google.com/web-toolkit/doc/latest/DevGuideUiEditors">GWT Editor</a> for binding.<br />
<br />
<a name='more'></a><br /><br />
<b>Database table</b><br />
<script src="https://gist.github.com/4212848.js?file=users_php.sql"></script>
<br />
<b>GXT and HttpProxy</b><br />
First of all the next interfaz and class are required<br />
<br />
MyAutoBeanFactory.java<br />
<script src="https://gist.github.com/4212989.js?file=MyAutoBeanFactory.java"></script>
<br />
MyHttpProxy.java<br />
<script src="https://gist.github.com/4212995.js?file=MyHttpProxy.java"></script>
<b> </b><br />
<b>GWT AutoBean</b><br />
With <a href="http://code.google.com/p/google-web-toolkit/wiki/AutoBean">GWT AutoBean</a> is easy to serialize/deserialize GWT Objects to json and vice versa,<br />
on the client side there is the UserProxy interface that represents the model<br />
<br />
<script src="https://gist.github.com/4213031.js?file=UserProxy.java"></script> UserListProxy represent a set of users<br />
<script src="https://gist.github.com/4213037.js?file=UserListProxy.java"></script>
<br />
With AutoBean the objects are created from a factory<br />
<br />
<script src="https://gist.github.com/4213062.js?file=AppAutoBeanFactory.java"></script>
<br />
<script src="https://gist.github.com/4213117.js?file=UserPresenter_snippet.java"></script>
<b>GXT Reader</b><br />
GXT Grid use a reader to parse the output of the server.<br />
<br />
<script src="https://gist.github.com/4213177.js?file=UserJsonReader.java"></script>
<b>GXT Grid</b><br />
<script src="https://gist.github.com/4213285.js?file=UserView_snippet.java"></script>
<br />
UserView.ui.xml<br />
<script src="https://gist.github.com/4213298.js?file=UserView.ui.xml"></script>
<br />
<b>Run the proyect</b><br />
You have to start your Apache Server and enable the following extensions for PostgreSQL and PDO:<br />
php_pdo_pgsql<br />
php_pgsql<br />
You have to set the root of your web server to the war of the project<br />
for example I use XAMPP and change the httpd.conf<br />
<script src="https://gist.github.com/4213374.js?file=httpd_snippet.conf"></script>
restart Apache Server.<br />
Set the parameters of connection to database PostgreSQL in war/config/connect.php<br />
I usually work on Firefox for GWT DevMode<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPpWtWMfvdXnQe7DGy1ughNTSbJCfKfXMJZqM2pfb3k1c5K55Zv0RHe0sIgVJ0yd7NYGyzsij1PQsuEIM4BCN-QG2W_z_Wkr_8eSPHK8OhmmqYz78NqmUTaCWNMheLTMZXRSobQVADAa2v/s1600/devmode.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPpWtWMfvdXnQe7DGy1ughNTSbJCfKfXMJZqM2pfb3k1c5K55Zv0RHe0sIgVJ0yd7NYGyzsij1PQsuEIM4BCN-QG2W_z_Wkr_8eSPHK8OhmmqYz78NqmUTaCWNMheLTMZXRSobQVADAa2v/s320/devmode.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFgbHRI-8iTLnLPw0d2lbNiQiSZjMPaAuh5dLlRBFWESHTPT88bjShOFM0yQeEM8PnUe7777hQ-qA_G-CXLfoZWS9PWvx6A0scpTvfA9TV5SI0SGPApGOJqKkQOelp9U3eELejH4qNRYcK/s1600/external_server.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFgbHRI-8iTLnLPw0d2lbNiQiSZjMPaAuh5dLlRBFWESHTPT88bjShOFM0yQeEM8PnUe7777hQ-qA_G-CXLfoZWS9PWvx6A0scpTvfA9TV5SI0SGPApGOJqKkQOelp9U3eELejH4qNRYcK/s320/external_server.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiejqqiRrQlIEr6DutiaJdlZmvTURpQOv6-agV0zXVac0assoHL-3eEmf_XdLXKZC52Blv5uDgGwIPhZBc4xRcU4C7y-usirzdJYtumJUaDkJJocCVkhdQUH2MMD3lJ9FY0xR2yYQr-vTmd/s1600/php_gwt_example.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiejqqiRrQlIEr6DutiaJdlZmvTURpQOv6-agV0zXVac0assoHL-3eEmf_XdLXKZC52Blv5uDgGwIPhZBc4xRcU4C7y-usirzdJYtumJUaDkJJocCVkhdQUH2MMD3lJ9FY0xR2yYQr-vTmd/s320/php_gwt_example.png" width="320" /></a></div>
<br />
<b>Compile GWT code to JS</b><br />
I compile GWT with <a href="https://developers.google.com/eclipse/">Google Plugin for Eclipse GPE </a><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdDbU6qdjZn9KIn2FPpge6DsV3dsD9HRpgzhqXYfEpjQqHd0fUqDeuzmOK4yEi9PyNX1JeOzXyuYlGlMqeamE2y7A_Vh8X4tbRGtfPO2EjDexDELoi5pgELsI3XruQuRnbBmCVLad2bkFl/s1600/php_gwt_compile.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdDbU6qdjZn9KIn2FPpge6DsV3dsD9HRpgzhqXYfEpjQqHd0fUqDeuzmOK4yEi9PyNX1JeOzXyuYlGlMqeamE2y7A_Vh8X4tbRGtfPO2EjDexDELoi5pgELsI3XruQuRnbBmCVLad2bkFl/s320/php_gwt_compile.png" width="320" /></a></div>
<br />
By default the compiled JS code is compressed.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLpilzf2eCVAxR1S6oPdhw0VLCV16EReKkzDnsZl1wxtTLawTq8QWrKKzXaYiR2ew2iGw805hLpNb2czQAv1M3gbPzhwdfk4WQhlkVPFfaXL6aPZ6jlAt7ujgsdNOGtK-r9aAt7f0EiUjF/s1600/php_gwt_output.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="285" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLpilzf2eCVAxR1S6oPdhw0VLCV16EReKkzDnsZl1wxtTLawTq8QWrKKzXaYiR2ew2iGw805hLpNb2czQAv1M3gbPzhwdfk4WQhlkVPFfaXL6aPZ6jlAt7ujgsdNOGtK-r9aAt7f0EiUjF/s320/php_gwt_output.png" width="320" /></a></div>
<br />
Then enter the url http://localhost/phpcrud.html#users<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ6X91keNBBE4aoHxduQafACSyW43I0hM5jHQf3DgE7gwCrwrodQvgwsRwKwEfwMTKcBjkpL1W99wRPeecSqt1AxsCL3Am44KP8BuebJ1iQ0EwHfFS8rhyphenhyphenuEI_R4sbwml_t8GLbo8W0YPG/s1600/php_gwt_final_app.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ6X91keNBBE4aoHxduQafACSyW43I0hM5jHQf3DgE7gwCrwrodQvgwsRwKwEfwMTKcBjkpL1W99wRPeecSqt1AxsCL3Am44KP8BuebJ1iQ0EwHfFS8rhyphenhyphenuEI_R4sbwml_t8GLbo8W0YPG/s320/php_gwt_final_app.png" width="320" /></a></div>
<br />
<b>The Server Side PHP</b><br />
I use simple PHP and PDO<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ-0Z3QrIensozWeHFGrdZDTntehA9kJKro7mu1l5jIFoyS_mteIt-XdLw3B-rwjH86v9Hi425aA1aclC0fw8IIAbERoXgUtTHHpbL9N-cLPNX0Lc5X73dA4I5U6iilZ7lUeQrf6DxEpul/s1600/php_server.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQ-0Z3QrIensozWeHFGrdZDTntehA9kJKro7mu1l5jIFoyS_mteIt-XdLw3B-rwjH86v9Hi425aA1aclC0fw8IIAbERoXgUtTHHpbL9N-cLPNX0Lc5X73dA4I5U6iilZ7lUeQrf6DxEpul/s320/php_server.png" width="245" /></a></div>
<a href="https://github.com/poseidonjm/GXT3-PHP/blob/master/war/config/connect.php">connect.php</a> <br />
<a href="https://github.com/poseidonjm/GXT3-PHP/blob/master/war/users/users.php">users.php</a><br />
<a href="https://github.com/poseidonjm/GXT3-PHP/blob/master/war/util/paginate.php">paginate.php</a><br />
Sorry if I am missing explain PHP code.<br />
<br />
I hope you can use GWT with any backend and <a href="https://www.google.com.pe/url?url=http://code.google.com/p/google-web-toolkit/wiki/AutoBean#GWT_AutoBean_framework&rct=j&q=GWT+AutoBean&usg=AFQjCNHqev-3cIe47RoRRWyzwvoVR_4pBw&sa=X&ei=B527UPzCBouQ8wTWyYDwDQ&ved=0CDUQygQwAA">AutoBean</a> is a nice feature of GWT.Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com2tag:blogger.com,1999:blog-7772385331860770062.post-33317219506802675472012-10-12T15:06:00.002-07:002016-02-05T11:51:59.091-08:00Introduction to Maven3 and GWT2.5-rc2My First presentation about gwt<br />
<br />
<a name='more'></a><br /><br />
<iframe allowfullscreen="allowfullscreen" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/14706075" style="border-width: 1px 1px 0; border: 1px solid #CCC; margin-bottom: 5px;" width="427"> </iframe> <br />
<div style="margin-bottom: 5px;">
<b> <a href="http://www.slideshare.net/poseidonJM/introduction-maven3-and-gwt25-rc2" target="_blank" title="Introduction maven3 and gwt2.5 rc2">Introduction maven3 and gwt2.5 rc2</a> </b> from <b><a href="http://www.slideshare.net/poseidonJM" target="_blank">rhemsolutions</a></b><br />
<br />
<b>The Second part using GWTP</b><br />
<b> </b> </div>
<iframe allowfullscreen="" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/14905984" style="border-width: 1px 1px 0; border: 1px solid #ccc; margin-bottom: 5px;" width="427"> </iframe> <br />
<div style="margin-bottom: 5px;">
<b> <a href="http://www.slideshare.net/poseidonJM/architecting-gw-tapplicationgwtplatform" target="_blank" title="Architecting your GWT applications with GWT-Platform">Architecting your GWT applications with GWT-Platform</a> </b> from <b><a href="http://www.slideshare.net/poseidonJM" target="_blank">rhemsolutions</a></b> </div>
Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com0tag:blogger.com,1999:blog-7772385331860770062.post-33856630371042333922012-07-03T18:23:00.000-07:002016-02-05T11:52:16.384-08:00GWT-Platform and GXT3Previously I wrote about GXT3 and RequestFactory to perform basic crud operations <a href="http://goo.gl/7ePse">http://goo.gl/7ePse</a>.<br />
This time I will be focused in GWTPlatform using GXT3 widgets. <br />
The source code is available through Github <a href="https://github.com/poseidonjm/GWTP-GXT3">https://github.com/poseidonjm/GWTP-GXT3</a><br />
<br />
<a name='more'></a><br /><br />
<b>GWT-Platform</b><br />
Used to simplify the MVP architecture with minimal boilerplate (<a href="http://code.google.com/p/gwt-platform/">GWTP page</a>)<br />
<br />
<b>GWTP Plugin for Eclipse</b><br />
You should install the plugin that offers wizards for create Presenters and Events<br />
Help > Install New Software<br />
http://plugin.gwt-platform.googlecode.com/hg/update<br />
I am using Eclipse Indigo. <br />
<br />
<b>Final Project</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTkEtIo8HyOJkv1vbB_UAPKNaOJIq9AZX1V_E99q-HzatfP_wjSBPjw9yUsBxJNViTbagdxixsLm4fCPdB2WUsgOmAAQo3VyGBiWhd1tAtuSWyR6_D7dOSEn8sLuAUKJHn-7k6BKbTkTZA/s1600/GWTP-GXT3-example.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTkEtIo8HyOJkv1vbB_UAPKNaOJIq9AZX1V_E99q-HzatfP_wjSBPjw9yUsBxJNViTbagdxixsLm4fCPdB2WUsgOmAAQo3VyGBiWhd1tAtuSWyR6_D7dOSEn8sLuAUKJHn-7k6BKbTkTZA/s400/GWTP-GXT3-example.png" width="400" /></a></div>
<br />
<br />
<br />
<b>Project Structure</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIFH7jAnqJCGob5Y3BUSiMpKw2VukT_ey4r5ps_Wn21uyzEyaLCc5kJF8Fyi54iA1eUZMD-GJ9ckHWyKbea4dY9L8u0KXbI8leWKcWh57NKfqMif8IZXxrH6ny6lIORAbYO8a6v7dzPevk/s1600/project-structure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIFH7jAnqJCGob5Y3BUSiMpKw2VukT_ey4r5ps_Wn21uyzEyaLCc5kJF8Fyi54iA1eUZMD-GJ9ckHWyKbea4dY9L8u0KXbI8leWKcWh57NKfqMif8IZXxrH6ny6lIORAbYO8a6v7dzPevk/s400/project-structure.png" width="311" /></a></div>
<br />
<b>CSS</b><br />
I copied the style of Sencha examples<br />
<br />
<b>Project Layout</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn2XG8-D4xhEO7PTvG1gwMnxdfSztjlQogQbb2o4DXSlFnLchCNFbgiWfpLsmL7fhgsqWKtM8UDYTnbsHXDng7pqs-_0vA08O61AthvPthGclDB5X7pMQQrBA6TAdXFUwytwghpIwwcBR0/s1600/layout-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn2XG8-D4xhEO7PTvG1gwMnxdfSztjlQogQbb2o4DXSlFnLchCNFbgiWfpLsmL7fhgsqWKtM8UDYTnbsHXDng7pqs-_0vA08O61AthvPthGclDB5X7pMQQrBA6TAdXFUwytwghpIwwcBR0/s400/layout-presenter.png" width="400" /></a></div>
LayoutPresenter.java is the main presenter it contains the header and footer of the page.<br />
LayoutPresenter is not a Place so the user cannot navigate.<br />
<br />
<b>Create a Presenter</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVW-xdR_2nNo7iBnqcXJho6Z_AQnrsSA-UXfzDUnlETr5oIldaw-87gOzJ8lDTHS7gWMYQf6sgubCuxJOOrqNKmPfdnHJDhjT88mQG40KWsHU_bt_IITC0E6FTR64904-h859FhZPi3OE7/s1600/new-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVW-xdR_2nNo7iBnqcXJho6Z_AQnrsSA-UXfzDUnlETr5oIldaw-87gOzJ8lDTHS7gWMYQf6sgubCuxJOOrqNKmPfdnHJDhjT88mQG40KWsHU_bt_IITC0E6FTR64904-h859FhZPi3OE7/s1600/new-presenter.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhJ5XsPBH7SlmGlLbrwumyEvX-ixuGEtHVys6tY44keNQJO5iXKB9uNkx7xL02Ad377jJVYGzAkhroR3O0q6mOFeaX7FS3uKw4VHoeX9IE87_PNUOHF8AlludIhlCWUFGazIdnheCxMEhb/s1600/first-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhJ5XsPBH7SlmGlLbrwumyEvX-ixuGEtHVys6tY44keNQJO5iXKB9uNkx7xL02Ad377jJVYGzAkhroR3O0q6mOFeaX7FS3uKw4VHoeX9IE87_PNUOHF8AlludIhlCWUFGazIdnheCxMEhb/s640/first-presenter.png" width="468" /></a></div>
<br />
I choose RevealRootContentEvent because this presenter takes all the screen.<br />
<br />
All presenters are composed of three files.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig_8hcciirChNBGWxkEcoMconiutP5MS3w2ZS9BL9bTEtFKVnq2eP_KKeoBW6KIducNEn9LhjZQjqGOlDen8DpBe1Bg95rTmLW062UqiboyryUa2D1bJLZvdoiQ-BeYg6_nQ8nuX5E0MzQ/s1600/presenter-files.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig_8hcciirChNBGWxkEcoMconiutP5MS3w2ZS9BL9bTEtFKVnq2eP_KKeoBW6KIducNEn9LhjZQjqGOlDen8DpBe1Bg95rTmLW062UqiboyryUa2D1bJLZvdoiQ-BeYg6_nQ8nuX5E0MzQ/s400/presenter-files.png" width="400" /></a></div>
<br />
All presenters have a inner interface that view implements.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH7Osx-QlqKAqsfoJBhy0szx_pkMMOg0KYylW_w3yhg588V6P0QiM5rga1oRySs4KsmZzy7n6fG_dvMLClN6PIO-KY4uDqQlDI88FVZNjxegVd1ngR_LCTNNyD3nop7q6KCEJ6DgtUwWW4/s1600/presenter-view.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjH7Osx-QlqKAqsfoJBhy0szx_pkMMOg0KYylW_w3yhg588V6P0QiM5rga1oRySs4KsmZzy7n6fG_dvMLClN6PIO-KY4uDqQlDI88FVZNjxegVd1ngR_LCTNNyD3nop7q6KCEJ6DgtUwWW4/s400/presenter-view.png" width="400" /></a></div>
<br />
<b>Presenter lifecycle</b><br />
<ul>
<li>Presenters are Singleton so it is instantiated once.</li>
<li>prepareFromRequest(): Is where you can get url parameters.</li>
<li>onBind(): Is called when the presenter is instantiated.</li>
<li>onReveal(): Is called whenever the Presenter was not visible on screen and becomes visible.</li>
<li>onHide(): Is called whenever the Presenter was visible on screen and is being hidden. </li>
<li>onReset(): Is called whenever the user navigates to a page that shows the presenter, whether it was visible or not.</li>
</ul>
References <a href="http://code.google.com/p/gwt-platform/wiki/GettingStarted#Presenter_lifecycle">GWTP Page</a> and <a href="http://www.youtube.com/watch?v=1iLg_qWTrXY&feature=relmfu">Dani GWTP Course</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlhf3L-9bWUOuK7TJsILRVV4RABLbw8xer5IsprYSQd7C01Vb-A2mASDwPBf1caQfFxlNqrwEh5y9v-MJNtnQJlldUVbx2erlVp9-3L-KkyRka5oDZgmwI2zrM5fq-HHJTmP0zXqE81p5f/s1600/presenter-lifecycle-paint.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlhf3L-9bWUOuK7TJsILRVV4RABLbw8xer5IsprYSQd7C01Vb-A2mASDwPBf1caQfFxlNqrwEh5y9v-MJNtnQJlldUVbx2erlVp9-3L-KkyRka5oDZgmwI2zrM5fq-HHJTmP0zXqE81p5f/s640/presenter-lifecycle-paint.png" width="435" /></a></div>
<br />
<b>Nested Presenters</b><br />
Your header, footer and menu are in one presenter the "parent presenter".<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm7kLrkWeiO-U-BVe3FvncgIFhW55GHY12e_ljH138TOI872byTW58Axqxgpav2959svlhcNMEzpyDFNCamVtTmaQ9RS9a2S2UfWufgPQF_vd-bkUS3DKYfDleFVrrRhWkeS4WC5G8Fs_x/s1600/nested-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm7kLrkWeiO-U-BVe3FvncgIFhW55GHY12e_ljH138TOI872byTW58Axqxgpav2959svlhcNMEzpyDFNCamVtTmaQ9RS9a2S2UfWufgPQF_vd-bkUS3DKYfDleFVrrRhWkeS4WC5G8Fs_x/s400/nested-presenter.png" width="400" /></a></div>
<br />
<b>Presenter Widget</b> <br />
Is for reusable graphical and logical code.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS10ahgR7_ffPe2gTmEAoa1akEOtuTfOPD66jJUx2KDNDv2Utmq21in_GOQQ3hDeBA3Z_5E8X94lo4N5KAFf5i34P64iGn0nmeDkxMaReeWGJIHrLEMuCyoawj5_zi0Did9XdI2BvFZrxu/s1600/presenter-widget.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS10ahgR7_ffPe2gTmEAoa1akEOtuTfOPD66jJUx2KDNDv2Utmq21in_GOQQ3hDeBA3Z_5E8X94lo4N5KAFf5i34P64iGn0nmeDkxMaReeWGJIHrLEMuCyoawj5_zi0Did9XdI2BvFZrxu/s1600/presenter-widget.png" /></a></div>
<br />
<br />
<br />
<b>LayoutPresenter.java</b><br />
<br />
<b>LayoutView.java</b><br />
<br />
<b>LayoutView.ui.xml</b><br />
<br />
<br />
<b>Create a Presenter Widget</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZbI1vNLEPPX2MghpNNmAosCkrcl3FuNJ043pFEllKFLpH7Ybwzz0LQpL3F3Mh5QA1o8A5WiNYQ-DoJ3dVYJBcjyOfklI3qn6i6ft7YC-S09_80ICrFOykED7_898XN7OPbLTeheu2sH_R/s1600/create-presenter-widget.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZbI1vNLEPPX2MghpNNmAosCkrcl3FuNJ043pFEllKFLpH7Ybwzz0LQpL3F3Mh5QA1o8A5WiNYQ-DoJ3dVYJBcjyOfklI3qn6i6ft7YC-S09_80ICrFOykED7_898XN7OPbLTeheu2sH_R/s640/create-presenter-widget.png" width="468" /></a></div>
<br />
<br />
<b>MenuPresenter.java</b><br />
<br />
<b>MenuView.java</b><br />
<br />
<b>MenuView.ui.xml</b><br />
<br />
<br />
<b>Create Default Presenter</b><br />
When you start you program the first page that you see is the default presenter.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPV_pqBNANiqtNqqlyR75M_HQbmJoMaBoqHmJ5v4Q6xj1ecQO1soPK_gm4UxfhSc4GHDFiTIH5qBWcXGhlVIkLf94E65JDjv5xlsaZTiG7JFCytW16IN0OJ50YR-bVD9TH9AEQMf-eDI-d/s1600/inicio-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPV_pqBNANiqtNqqlyR75M_HQbmJoMaBoqHmJ5v4Q6xj1ecQO1soPK_gm4UxfhSc4GHDFiTIH5qBWcXGhlVIkLf94E65JDjv5xlsaZTiG7JFCytW16IN0OJ50YR-bVD9TH9AEQMf-eDI-d/s640/inicio-presenter.png" width="516" /></a></div>
<br />
<br />
<b>Create Colaborador Presenter</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieoBFwY97BJ8G87uRp6CS3mQli7mpsT5oO51j6kk79rNtJt27JimcKbWq6udJ8xn7a2V94FWvYynCoQ2xnYUxu3XvKDW9sD8IPlQzyG6ceqWe5_Eo03XJAwLXepaGrju0OGKF7SP82xhOJ/s1600/colaborador-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieoBFwY97BJ8G87uRp6CS3mQli7mpsT5oO51j6kk79rNtJt27JimcKbWq6udJ8xn7a2V94FWvYynCoQ2xnYUxu3XvKDW9sD8IPlQzyG6ceqWe5_Eo03XJAwLXepaGrju0OGKF7SP82xhOJ/s640/colaborador-presenter.png" width="515" /></a></div>
<br />
<b>Tokens</b><br />
Most presenters have a token so the user can navigate.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZh5D5IbeY-OwKM1VExyAyZWVh0N4zs0XqyNRxK_8CNFDtLqls3-hkh5dZ8ucTneNLCjVHyf-UQsEgRGU6vn5OvkMxDAs88cl92XMFUtOicrIsVnC4Uvp-wTgaioGSArgNJaP9A0SftZEg/s1600/tokens.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="120" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZh5D5IbeY-OwKM1VExyAyZWVh0N4zs0XqyNRxK_8CNFDtLqls3-hkh5dZ8ucTneNLCjVHyf-UQsEgRGU6vn5OvkMxDAs88cl92XMFUtOicrIsVnC4Uvp-wTgaioGSArgNJaP9A0SftZEg/s400/tokens.png" width="400" /></a></div>
<br />
For example #colaboradores is a token that identifies the program Colaboradores. When there is not token the default presenter is shown.<br />
<br />
You can navigate from one presenter to another by:<br />
<ul>
<li>Typing another url</li>
<li>Using a Hyperlink Widget</li>
<li>Using a Place Request</li>
</ul>
References <a href="http://www.youtube.com/watch?v=1iLg_qWTrXY&feature=relmfu">Dani GWTP course </a><br />
<br />
For Example MenuPresenter use Place Request to navigate through the programs. <br />
<br />
<b>Popup Presenters</b><br />
Is a presenter widget that is shown inside a popup dialog.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP3LqjUzre0H_rU-kVCpI3mLnfGwSrKdcsHwSPHZG_5pxtaNTUB0xS3QWvgJFJ_E3n14vxj3gVlp2a9ym_b1PA51kozOsTuvx5OyWvydFOMVnc4AQfIfs6ZqgJ3yf52re6Ab5l9PjB0epL/s1600/popup-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="267" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjP3LqjUzre0H_rU-kVCpI3mLnfGwSrKdcsHwSPHZG_5pxtaNTUB0xS3QWvgJFJ_E3n14vxj3gVlp2a9ym_b1PA51kozOsTuvx5OyWvydFOMVnc4AQfIfs6ZqgJ3yf52re6Ab5l9PjB0epL/s400/popup-presenter.png" width="400" /></a></div>
<br />
<b>Create a Popup Presenter</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsuTyejYBgvk8rApes9X-MbyhOZvIZyfCfpEBCiM9GNj__VZLGDlFnmBmXb3AfvHEd2eVua1ayKXE28TgSyIW_ag7Jw844PjtItbJuLnzD3cDfzpbL_G55wWiVyGUP_wvKrTFZAf3CFjK9/s1600/create-popup-presenter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsuTyejYBgvk8rApes9X-MbyhOZvIZyfCfpEBCiM9GNj__VZLGDlFnmBmXb3AfvHEd2eVua1ayKXE28TgSyIW_ag7Jw844PjtItbJuLnzD3cDfzpbL_G55wWiVyGUP_wvKrTFZAf3CFjK9/s640/create-popup-presenter.png" width="468" /></a></div>
<br />
<br />
<b>Popup Presenters and GXT3</b><br />
Usually popup views extend PopupViewImpl or PopupViewWithUiHandler. But it works if you use GWT PopupPanel or DialogBox or whatever extend GWT PopupPanel.<br />
I wanna use GXT Window like Popup Presenter so I copied PopupViewImpl and PopupViewWithUiHandler and change GWT PopupPanel by GXT Window.<br />
<br />
<b>GXTPopupViewImpl.java</b><br />
<b><br /></b>
<br />
<b>GXTPopupViewWithUiHandlers.java</b> <br />
Its all about GWTP and GXT3<br />
Greetings.<br />
<br />
_______________________________________________________________________________<br />
UPDATED<br />
GXTPopupViewImpl.java and
GXTPopupViewWithUiHandlers.java are available through maven central
<br />
gwtp-gxtwindow-1.0.jar<br />
<a href="http://search.maven.org/#search%7Cga%7C1%7Ccom.rhemsolutions">http://search.maven.org/#search%7Cga%7C1%7Ccom.rhemsolutions</a><br />
<br />
add to your GWT module<br />
<br />
<inherits name='com.rhemsolutions.PopupWindow'/><br />
<br />Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com2tag:blogger.com,1999:blog-7772385331860770062.post-39766207712445498722012-06-11T11:48:00.000-07:002016-02-05T11:52:33.974-08:00Sencha GXT3 RequestFactory Guice JPAI am now starting a new blogspot. Next I will describe a Basic CRUD example with GXT Grid.<br />
The project was build with Maven and is available via GIT <a href="https://github.com/poseidonjm/basic-crud">https://github.com/poseidonjm/basic-crud</a><br />
If you don't have Egit you can install Help -> Install New Software...<br />
<br />
http://download.eclipse.org/egit/updates<br />
<br />
<a name='more'></a><br /><br />
I am using Eclipse Java EE IDE for Web Developers.<br />
You should install Maven <a href="http://maven.apache.org/download.html">http://maven.apache.org/download.html</a> download <a class="externalLink" href="http://www.apache.org/dyn/closer.cgi/maven/binaries/apache-maven-3.0.4-bin.zip" style="background-color: #dddddd; background-image: none; color: #6688aa; font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 11px; padding-right: 0px; text-align: -webkit-left; text-decoration: none;">apache-maven-3.0.4-bin.zip</a><br />
<br />
Install maven plugin Help -> Install New Software...<br />
<a href="http://www.blogger.com/m2e-wtp%20-%20http://download.jboss.org/jbosstools/updates/m2eclipse-wtp">m2e-wtp - http://download.jboss.org/jbosstools/updates/m2eclipse-wtp</a><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<b>Final Project</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivkNlR7EdKul9bWMLqmFNskthBwLUbTkXvgF6VtKz9znJJjlg3QjwjEnC3tOLKDbcrnkxM24XJCtWMirilozAnFD2ASVXLEhuR_VCc-qWPKOW7L4t5PqwFjttLh6M0C7-dyOxdjNyuuklr/s1600/final-crud.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivkNlR7EdKul9bWMLqmFNskthBwLUbTkXvgF6VtKz9znJJjlg3QjwjEnC3tOLKDbcrnkxM24XJCtWMirilozAnFD2ASVXLEhuR_VCc-qWPKOW7L4t5PqwFjttLh6M0C7-dyOxdjNyuuklr/s320/final-crud.png" width="320" /></a></div>
<br />
<b>Database Table</b><br />
I am using postgreSQL 8.4<br />
<br />
<script src="https://gist.github.com/2912263.js?file=colaboradores.sql">
</script>
<b>General Structure</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGRPQhvMn9wDdvKHcie9PuI8IjsngV-KlcGQB_CmvutaisBrFwHy48gIpY_w_9CKgGgvnE32TlVbwLmokOcuBZEivvJrO1CwIw4UPOdas5ZeS_L51SZUkKlty7_yIozwhf0aBgsbPAQfhw/s1600/project-maven.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGRPQhvMn9wDdvKHcie9PuI8IjsngV-KlcGQB_CmvutaisBrFwHy48gIpY_w_9CKgGgvnE32TlVbwLmokOcuBZEivvJrO1CwIw4UPOdas5ZeS_L51SZUkKlty7_yIozwhf0aBgsbPAQfhw/s320/project-maven.png" width="312" /></a></div>
<b>Project Structure</b><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf97YmTaZV9VsB6JUxOALRzVxIDe-itYhJzAAtAQVRJQd0Kd8tA8DNNtqF93a2gyfM9_EIWaN2tMFoqsNml2Lh1V5EY3d0v9DbuhXj5OCf777Z85oCW69x9gNXxedWNAlXSem1Z75nXvyW/s1600/java-structure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf97YmTaZV9VsB6JUxOALRzVxIDe-itYhJzAAtAQVRJQd0Kd8tA8DNNtqF93a2gyfM9_EIWaN2tMFoqsNml2Lh1V5EY3d0v9DbuhXj5OCf777Z85oCW69x9gNXxedWNAlXSem1Z75nXvyW/s320/java-structure.png" width="163" /></a></div>
G<b>eneral POM.xml</b><br />
<script src="https://gist.github.com/2902501.js?file=pom.xml">
</script>
<b>GWT Module</b><br />
<script src="https://gist.github.com/2902531.js?file=example.gwt.xml">
</script>
Here I am include modules like RequestFactory, GXT, UIBinder, GIN and set my locale to es_PE (spanish-Perú).<br />
<b><br /></b>
<b>EntryPoint</b><br />
<script src="https://gist.github.com/2902572.js?file=example.java">
</script>
So where is the code? Simple I am using Gin and is like Guice for GWT projects. It means you can use the powerful Dependency Intection in your GWT code.<br />
<br />
<b>What is Dependency Intection?</b><br />
In a nutshell "Never use <span style="color: #990000;">new</span> use @Inject instead". Guice will create your object and initialized injected fields.<br />
<br />
In GIN I need a Ginjector and create this with GWT.create().<br />
private final ClientGinjector injector = GWT.create(ClientGinjector.class);<br />
<br />
<b>Ginjector code</b><br />
<script src="https://gist.github.com/2902611.js?file=ClientGinjector.java">
</script>
Here I get a ColaboradorPanel to attach to the RootPanel. A Ginjector need a Module.<br />
<br />
<b>Client Module</b><br />
The next code was extracted from <a href="http://cleancodematters.com/2011/05/19/gwt-requestfactory_with_gin/">http://cleancodematters.com/2011/05/19/gwt-requestfactory_with_gin/</a><br />
<script src="https://gist.github.com/2902630.js?file=ClientModule.java">
</script>
Here I configure how GIN will create objects. My Messages Interface should be a Singleton, my ClientBundle AppImages too. In RequestFactory is needed an EventBus here I am using a SimpleEventBus and is a Singleton. There is a Provider method createRequestFactory that create my AppRequestFactory Interface and initialized it with a SimpleEventBus. More about GIN <a href="http://code.google.com/p/google-gin/">http://code.google.com/p/google-gin/</a>.<br />
<br />
<b>ColaboradorPanel</b><br />
<script src="https://gist.github.com/2902705.js?file=ColaboradorPanel.java">
</script>
In GWT there is not Java Reflection and GXT need access to the properties. For that purpose here is the interface ColaboradorProxyProperties.<br />
<br />
I created a SaveEvent to be fired when a user click on Save Button.<br />
<br />
<b>SaveEvent</b><br />
<script src="https://gist.github.com/2902724.js?file=SaveEvent.java">
</script>
Inside there is already created a SaveHandler.<br />
I created this class using a GWTP Plugin for Eclipse <a href="http://code.google.com/p/gwt-platform/wiki/EclipsePlugin">http://code.google.com/p/gwt-platform/wiki/EclipsePlugin</a> Once installed you can use this wizard to easily create your events.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCcVI_q7Ovvl1fjV0Fn1SCm7iCSw0ZW7axT4LD4-jKDZzBhGqNnHZ8ZwRKBw7Evjq1EOqIDe_iS4vzWZjShDEbZW_FyUuF1FAPU0UST8W2ep2GmwJ5RRtRiWvSih2CAbRCstVCOh1lCnZI/s1600/events.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCcVI_q7Ovvl1fjV0Fn1SCm7iCSw0ZW7axT4LD4-jKDZzBhGqNnHZ8ZwRKBw7Evjq1EOqIDe_iS4vzWZjShDEbZW_FyUuF1FAPU0UST8W2ep2GmwJ5RRtRiWvSih2CAbRCstVCOh1lCnZI/s1600/events.png" /></a></div>
<br />
I entered the EventName: SaveEvent and check the Has Handlers box.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxRkSeCuhKLjHW1xdLfC_HIOJWlVtqhTpxrD0YhsVUHgIMCZVPfHEfWw9fnh5O3jnqz8_uWEWdX-TxmekR71wuT9YiCrwO4QrvIj_GDSxZQUDpz4Vy2cBBj4jTIf0yP5M3EPFcu8ZbgskN/s1600/save-event.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxRkSeCuhKLjHW1xdLfC_HIOJWlVtqhTpxrD0YhsVUHgIMCZVPfHEfWw9fnh5O3jnqz8_uWEWdX-TxmekR71wuT9YiCrwO4QrvIj_GDSxZQUDpz4Vy2cBBj4jTIf0yP5M3EPFcu8ZbgskN/s320/save-event.png" width="320" /></a></div>
<br />
The Editor is the Dialog where the user entered your information and click on Save button. Here the SaveEvent is fired and the method save of SaveHandler is executed. Here I call the flush method to update the object modified in the editor. An next if the driver has not eny errors I hide the Editor and fire the context RequestContext.<br />
<br />
<b>What Is a RequestContext</b><br />
In RequestFactory all changes in an object are done inside a context. When you want to persist your changes call the fire methot of a context. Your changes are sent to the server and are saved to a database. It means you can make many changes before sent your changes to the server.<br />
<br />
Next I Inject Messages interface using Field Injection.<br />
@Inject Messages messages;<br />
<br />
Then I use Constructor Injection to initialized required variables.<br />
<br />
@Inject<br />
public ColaboradorPanel(final Binder uiBinder, EventBus eventBus, Provider<AppRequestFactory> provider, Driver driver, ColaboradorEditor editor)<br />
<br />
<b>What happens first Constructor Injection or Field Injection?</b><br />
The answer is Constructor Injection. It means you can't use messages variable inside the constructor because you will get a NullPointerException. If you need a variable inside a constructor inject it using Constructor Injection.<br />
<br />
For create a GXT Grid you need create a proxy, loader and a store. Inside the proxy I use two helper function createRequestSortInfo createRequestFilterConfig to get sort info and filter info. This is needed because in Request Factory you cannot sent any object to the server. You only can sent interfaces that extends ValueProxy or EntityProxy. You sent a EntityProxy if there is an Entity Implementation on the server It means if you have a table in a database. For other objects use ValueProxy.<br />
<br />
For create objects and edit In RequestFactory with GWT Editor. I use one method persist()<br />
<br />
<b>Create an Object with GWT Editor</b><br />
First I declare a field member<br />
private ColaboradorProxy colaborador;<br />
<br />
If I wanna create an object I create en empty Object<br />
colaborador = cs.create(ColaboradorProxy.class);<br />
<br />
Then bind the object with the Editor<br />
driver.edit(colaborador, cs);<br />
<br />
Next show the Editor<br />
editor.show(messages.addColaborador());<br />
<br />
When the user see the Editor or Dialog will see empty TextFields because is binded with an empty object.<br />
Then the user fill the Form and click on Save. The SaveEvent is fired and The SaveHandler is executed. Here I still have an empty object I you do a System.out.println(colaborador.getAge()) you will get nothing then I call the method flush() on driver and the empty object is update with the editor information the user was entered next you can do System.out.println(colaborador.getAge()) an will get what you want.<br />
Next I fire the context and sent my changes to server.<br />
<br />
<b>Edit an Object with GWT Editor</b><br />
Get the object selected<br />
colaborador = grid.getSelectionModel().getSelectedItem();<br />
<br />
And repeat the above steps.<br />
When the user see the editor will see the information selected and can do changes and save them because It is binded with an selected object and is not empty. Here the same happens if you don't call the method flush() on driver your object won't be updated.<br />
<br />
<b>Two way for creating UiBinder</b><br />
When you use UiBinder you should have two files ColaboradorPanel.java and ColaboradorPanel.ui.xml<br />
Your java file may be writed in two ways:<br />
First way
<script src="https://gist.github.com/2911824.js?file=ColaboradorPanel.java">
</script>
<br />
If you want to extend from Window you can see <a href="http://www.sencha.com/forum/showthread.php?181348-(beta2)-Editor-extends-Window-doesn-t-work">http://www.sencha.com/forum/showthread.php?181348-(beta2)-Editor-extends-Window-doesn-t-work</a><br />
Second way
<script src="https://gist.github.com/2911845.js?file=ColaboradorPanel.java">
</script>
<br />
<b>ColaboradorPanel.ui.xml</b><br />
<script src="https://gist.github.com/2903024.js?file=ColaboradorPanel.ui.xml">
</script>
<br />
<b>ColaboradorEditor.java</b><br />
All fields that need binding should be declared like class fields. If the widget is only in UiBinder and not declared like class field the binding with GWT Editor does not work.<br />
In UiBinder all widgets are create by GWT. If you need pass an argument by UiBinder you can use<br />
@UiFactory <a href="http://blog.jeffdouglas.com/2010/02/24/gwt-uibinder-passing-objects-to-widgets/">http://blog.jeffdouglas.com/2010/02/24/gwt-uibinder-passing-objects-to-widgets/</a><br />
In another way you can pass the argument in java code and your field should be annotated with @UiField(provided=true) what means the object will be created by java code and not by UiBinder.<br />
For add events I use @UiHandler("save") annotation where "save" identifies the button Save.<br />
<br />
<b>ColaboradorEditor.ui.xml</b><br />
<script src="https://gist.github.com/2912154.js?file=ColaboradorEditor.ui.xml">
</script>
<b>AppImages.java</b><br />
<script src="https://gist.github.com/2912164.js?file=AppImages.java">
</script>
I am using a ClientBundle for application images and this class is injected by GIN where is needed and is not necessary use GWT.create.<br />
<br />
<b>EntityBase.java</b><br />
<script src="https://gist.github.com/2912240.js?file=EntityBase.java">
</script>
There is not database table associated with this class. RequestFactory need a two fields in every domain class "id" and "version" these are columns in database table too.<br />
<br />
<b>Colaborador.java</b><br />
<script src="https://gist.github.com/2912273.js?file=Colaborador.java">
</script>
Here I have my entity class. In eclipse I can use a wizard to generate this entity class.<br />
First you should enable JPA Facet in your eclipse project.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDWL9fsPg5zmX5BQi3bY3iA2FeRLk1QBZY6AOEgHTESRpT-1jn6NGV4cOyu4FIs1fKCHvY1n_wu3f-XcAwhE-4GoMkfXAAEshBUo6hLY5QK81QW06hFlYxSIS2hPL0GFDn-WVxLkQKqAVo/s1600/facet.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDWL9fsPg5zmX5BQi3bY3iA2FeRLk1QBZY6AOEgHTESRpT-1jn6NGV4cOyu4FIs1fKCHvY1n_wu3f-XcAwhE-4GoMkfXAAEshBUo6hLY5QK81QW06hFlYxSIS2hPL0GFDn-WVxLkQKqAVo/s320/facet.png" width="320" /></a></div>
<br />
You need configure a data source Window -->Show View --> Data Source Explorer<br />
and create a new connection<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQqaAvMRC-Lz4eJPdvEhdjDKSwdvxXVxufMbxYWlaytC6PKqPHTmODNxYfhnz3F3ftiChH4wR4_mTLx0U8dN7jL_T1JO0TGjWFaVFdBA3PQ1ggrbxhUBDW35H4Ucz11jl770KW9snxQU3L/s1600/connection.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQqaAvMRC-Lz4eJPdvEhdjDKSwdvxXVxufMbxYWlaytC6PKqPHTmODNxYfhnz3F3ftiChH4wR4_mTLx0U8dN7jL_T1JO0TGjWFaVFdBA3PQ1ggrbxhUBDW35H4Ucz11jl770KW9snxQU3L/s320/connection.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVbQAAC9bT1HhWPmCglJJlucfAnSUO3mhK9CTV98ZhaPHUMHhfAfpdTFf71AxVKDSpOSA-tPxf7w97YxxcbybAQVDmimlzv74av02-9Q-9sMZS1j39lnYdBuwL1a-CjS77UvYE_-B54-y0/s1600/driver.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVbQAAC9bT1HhWPmCglJJlucfAnSUO3mhK9CTV98ZhaPHUMHhfAfpdTFf71AxVKDSpOSA-tPxf7w97YxxcbybAQVDmimlzv74av02-9Q-9sMZS1j39lnYdBuwL1a-CjS77UvYE_-B54-y0/s320/driver.png" width="320" /></a></div>
<br />
Right click on your package and select New --> JPA Entities from tables<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB2-YBPAcFoqrR3uMEhw7n9HhTqAeJxvpkurjWp1NLI_lOVO1E0hM8y4JknSZxCyps3vE3bUbV6o9A0DtgbXvrHQMdNhOF6Igoc4IAdqyqSOdki_edO0KpPPUWE_8p4cFFN6oIxayt8JQq/s1600/select-tables.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB2-YBPAcFoqrR3uMEhw7n9HhTqAeJxvpkurjWp1NLI_lOVO1E0hM8y4JknSZxCyps3vE3bUbV6o9A0DtgbXvrHQMdNhOF6Igoc4IAdqyqSOdki_edO0KpPPUWE_8p4cFFN6oIxayt8JQq/s320/select-tables.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzgu_iNfP7YYZ2hRvaJisA2wQE6woWAPuS9t1r5xiTxmJPXXH0f3EJZ7Dhl4iIjtbANE2msdYmeTIQa_z4lUGvCf68qjzNyEXG5RHHMAXvq56FGUfVaCzwUCZmpZe76-6u1ViX1ljhW4N/s1600/identity.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuzgu_iNfP7YYZ2hRvaJisA2wQE6woWAPuS9t1r5xiTxmJPXXH0f3EJZ7Dhl4iIjtbANE2msdYmeTIQa_z4lUGvCf68qjzNyEXG5RHHMAXvq56FGUfVaCzwUCZmpZe76-6u1ViX1ljhW4N/s320/identity.png" width="271" /></a></div>
<br />
RequestFactory with Guice<br />
RequestFactory is not integrate with Guice por default. In that case there is a helpful set of classes that make RequestFactory injectable <a href="https://github.com/etiennep/injected-requestfactory">https://github.com/etiennep/injected-requestfactory</a>. I only did copy and paste of that classes.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOUU-T9Ky5wUZc8t0E6-3YyPNlJ3tGF1TLkR4BFAHVLvB70j0pXTEEzMATMtq64CKrxABJhD8-wnBOJLKa3M8MCB8wG2l7dysvqAfGBO1KseJ8wChzGBo59r0iQ-cJddn4YJBb2v8kk87t/s1600/injected-requestfactory.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOUU-T9Ky5wUZc8t0E6-3YyPNlJ3tGF1TLkR4BFAHVLvB70j0pXTEEzMATMtq64CKrxABJhD8-wnBOJLKa3M8MCB8wG2l7dysvqAfGBO1KseJ8wChzGBo59r0iQ-cJddn4YJBb2v8kk87t/s1600/injected-requestfactory.png" /></a></div>
<br />
<b>web.xml</b><br />
<script src="https://gist.github.com/2912475.js?file=web.xml">
</script>
Here I configure GuiceFilter. And GuiceServletContextListener.<br />
<br />
<b>MyGuiceServletConfig.java</b><br />
<br />
<script src="https://gist.github.com/2912494.js?file=MyGuiceServletConfig.java">
</script><br />
In Guice you can configure all servlets and filters in java code here I configure my InjectedRequestFactoryServlet not use web.xml anymore. More info <a href="http://code.google.com/p/google-guice/wiki/ServletModule">http://code.google.com/p/google-guice/wiki/ServletModule</a>.<br />
<br />
<b>persistence.xml</b><br />
<script src="https://gist.github.com/2912534.js?file=persistence.xml">
</script>
Here I configured my connections parameters.<br />
<br />
<b>ColaboradorDao.java</b><br />
<script src="https://gist.github.com/2912551.js?file=ColaboradorDao.java">
</script>
Here I use injection fields to inject the Entity Manager and an Util class Paginate. Entity manager is initialized by Guice <a href="http://code.google.com/p/google-guice/wiki/JPA">http://code.google.com/p/google-guice/wiki/JPA</a> .<br />
In JPA all objects are not persisted before commit the transaction. In Guice there is a useful annotation @Transactional <a href="http://code.google.com/p/google-guice/wiki/Transactions">http://code.google.com/p/google-guice/wiki/Transactions</a> that made the method transactional.<br />
<br />
<b>ColaboradorPagingLoadResultBean.java</b><br />
<script src="https://gist.github.com/2912617.js?file=ColaboradorPagingLoadResultBean.java">
</script>
This class that extend PagingLoadResultBean is needed for objects that will be shown in a GXT Grid.<br />
<br />
<b>Paginate.java</b><br />
<script src="https://gist.github.com/2912649.js?file=Paginate.java">
</script>
This class use CriteriaBuilder for paginate a database table. <a href="http://www.ibm.com/developerworks/java/library/j-typesafejpa/">http://www.ibm.com/developerworks/java/library/j-typesafejpa/</a><br />
<br />
<b>EntityLocator.java</b><br />
<script src="https://gist.github.com/2912674.js?file=EntityLocator.java">
</script>
In Request Factory you work with interfaces that are Proxy and require a locator. This is a generic locator for all Proxies.<br />
<br />
<b>ColaboradorProxy.java</b><br />
<script src="https://gist.github.com/2912701.js?file=ColaboradorProxy.java">
</script>
This is the object that you use in your GWT code and is initialized using GWT.create sent to the server and Request Factory does the magic to translate this proxy in an entity object. This proxy extend EntityProxy because represent a domain class or a database table.<br />
<br />
<b>ColaboradorService.java</b><br />
<script src="https://gist.github.com/2912750.js?file=ColaboradorService.java">
</script>
For each database table I create a Service or RequestContext. The proxy ColaboradorPagingLoadResultProxy is required for GXT.<br />
<br />
<b>AppRequestFactory.java</b><br />
<script src="https://gist.github.com/2912764.js?file=AppRequestFactory.java">
</script>
Here I configure all my services.<br />
<br />
<b>Internationalization with GWT</b><br />
I use two properties files<br />
<br />
Messages.properties<br />
<script src="https://gist.github.com/2912793.js?file=Messages.properties">
</script>
<br />
Messages_es_PE.properties<br />
<script src="https://gist.github.com/2912800.js?file=Messages_es_PE.properties">
</script>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRjWKPqYT7yI6u_qpYUNqbzUjJAbCtwMfSoP56DuMq_I2FLfNQ_Vdt0fd7lmm9xdnHALA4rBdKqNzGVtsLLg-Qji2yZK7i3MdfArSXCLyVNTzHpgyT9sfiRRSMC_Za3OxBNoLCq4NQSO7l/s1600/i18n.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRjWKPqYT7yI6u_qpYUNqbzUjJAbCtwMfSoP56DuMq_I2FLfNQ_Vdt0fd7lmm9xdnHALA4rBdKqNzGVtsLLg-Qji2yZK7i3MdfArSXCLyVNTzHpgyT9sfiRRSMC_Za3OxBNoLCq4NQSO7l/s1600/i18n.png" /></a></div>
There is needed an aditional interface. In GWT that interface could be generated.<br />
Go to project path and write the command <span style="color: #666666;">mvn gwt:i18n</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixgBOBdL5RpwujqdakKitZqPN54yFSfzMQh6hN7Kw293KQu-oDQGiPyjvWaxuPfvFuN5mDCGyPmX4GW9Kxf76CYhBXt80YSPwKM-GS4hUP8lNk-0jcagSUlc7YMySp_uTrCfK2YBaUMU_s/s1600/mvn-i18n.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixgBOBdL5RpwujqdakKitZqPN54yFSfzMQh6hN7Kw293KQu-oDQGiPyjvWaxuPfvFuN5mDCGyPmX4GW9Kxf76CYhBXt80YSPwKM-GS4hUP8lNk-0jcagSUlc7YMySp_uTrCfK2YBaUMU_s/s320/mvn-i18n.png" width="320" /></a></div>
<br />
Is generated in target/generated-sources<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQYvmftlSF0clWk_hYd3i0DhguPDbqm01d6VOAg9asqOq1jmV9aiTuE2TDmItniujrfMAW0vhYk4rpTEYAYu6_y4KjcN0C7c_Nnwu1oPiBagXycKnDr8YScbY4gL-tnyfKNGHM6j3NElyF/s1600/messages.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQYvmftlSF0clWk_hYd3i0DhguPDbqm01d6VOAg9asqOq1jmV9aiTuE2TDmItniujrfMAW0vhYk4rpTEYAYu6_y4KjcN0C7c_Nnwu1oPiBagXycKnDr8YScbY4gL-tnyfKNGHM6j3NElyF/s1600/messages.png" /></a></div>
<br />
You should add to build path right click on generated-sources/gwt folder Build Path --> Use as Source Folder.<br />
You can use command<span style="color: #444444;"> mvn gwt:run</span> to launch the Hosted Mode.<br />
<br />Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com11tag:blogger.com,1999:blog-7772385331860770062.post-21301502624133250392012-02-16T19:26:00.000-08:002016-02-05T11:55:11.836-08:00Basic Grid with GXT3<br />
<span class="spanish">En el siguiente ejemplo uso</span>
<span class="english">I am using</span> GWT 2.4, AppEngine 1.7.0<br />
<br />
<a name='more'></a><br /><br />
<span class="spanish">A continuación muestro un pantallazo del ejemplo.</span>
<span class="english">Next is the screenshot of the example</span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3cH4wqU1TBX3sarZSHmghKKFXDUI6C-TnWT4cT8ADlZE7-pnH-_K4zebzBj0JJciTQ23fvEdzLHn2PLJ07XtLreJ-3M4GnrE48n_kBqU8gBiW5IhnFyWA3HeSUw1APjuh1nHX0k11MjSj/s1600/imagen6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3cH4wqU1TBX3sarZSHmghKKFXDUI6C-TnWT4cT8ADlZE7-pnH-_K4zebzBj0JJciTQ23fvEdzLHn2PLJ07XtLreJ-3M4GnrE48n_kBqU8gBiW5IhnFyWA3HeSUw1APjuh1nHX0k11MjSj/s320/imagen6.png" width="320" /></a></div>
<span class="spanish">El codigo Fuente lo encuentran aqui:</span><span class="english">The source code is here:</span> <a href="https://github.com/poseidonjm/GAE-GXT3">https://github.com/poseidonjm/GAE-GXT3</a><br />
Demo <a href="http://gae-gxt3-basic.appspot.com/">http://gae-gxt3-basic.appspot.com/</a><br />
<span class="spanish">La estructura del proyecto:</span><span class="english">The project organization:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNtuPNT1rO59lvJXs60ESlWerQIN8tqxb4oLyGhKayV89xM6FD5V5EtbULOubIiIPolBAiggI32GPi9zEYMZqoe2YqKTgEt_UBBsiEjUxzw-L96TLvHAj62sQOGbDidxcmE5wYoCJAwUJj/s1600/imagen7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNtuPNT1rO59lvJXs60ESlWerQIN8tqxb4oLyGhKayV89xM6FD5V5EtbULOubIiIPolBAiggI32GPi9zEYMZqoe2YqKTgEt_UBBsiEjUxzw-L96TLvHAj62sQOGbDidxcmE5wYoCJAwUJj/s320/imagen7.png" width="188" /></a></div>
<br />
<span class="spanish">
<b>Introducción:</b><br /> A continuación voy a mostrar un ejemplo básico de como hacer un CRUD utilizando GXT3 RequestFactoryEditorDriver teniendo en el servidor a Objectify como medio de persistencia. Al igual que en posts anteriores voy a utilizar AppEngine, pero igualmente podria utilizar una base de datos relacional y JPA para la persistencia.<br />
</span>
<span class="english"><b>
Introduction:</b></span><br />
<span class="english">In this post I show a basic example of how to build a CRUD using GXT3 and RequestFactoryEditorDriver with Objectify and AppEngine, but I could use a relational database and JPA for the ORM.</span>
<span class="spanish"><b>EXT GWT 2 a GXT3</b><br />
La nueva versión de GXT3 tiene como objetivo hacerlo más compatible con GWT. Por ejemplo utilizar los eventos de GWT, soporte para UIBinder, hacer el binding con el Editor Framework, etc.Más información lo pueden encontrar en la presentación de senchacon2011 <a href="http://www.slideshare.net/senchainc/migrating-from-ext-gwt-2x-to-30-10013673">http://www.slideshare.net/senchainc/migrating-from-ext-gwt-2x-to-30-10013673</a><br />
y el video <a href="http://vimeo.com/33640855">http://vimeo.com/33640855</a>.<br />
Debido a esta actualización varios componentes de gxt2 fueron removidos para ser reemplazados por componentes propios de GWT. Por ejemplo El FormBinding fue removido para se reemplazado por el <a href="http://vivagwt.blogspot.com/2011/09/gwt-editor.html">Editor de GWT</a>. En GXT2 los modelos debían heredar del ModelData para poder se mostrados en los componentes de datos. El objetivo del uso del ModelData era para poder acceder a las propiedades de los objetos ya que GWT no soporta Java Reflection. En la versión de GXT3 los objetos son simples POJOS (Objetos planos) y para acceder a las propiedades de los objetos utiliza una interfaz llamada PropertyAccess<T> . Para lograr esto el equipo de EXT GWT de Sencha tuvo que reescribir los stores desde cero.<br />
Otro cambio importante es el renderizado de componentes. En GWT los componentes se renderizan cuando se llama al constructor del objeto. lo que no ocurría en GXT2. Pero en GXT3 ya es posible acceder al DOM desde el constructor ya que se renderiza al igual que un componente de GWT.<br />
En GXT3 se hizo una cambio en los Layouts <a href="http://www.slideshare.net/senchainc/ext-gwt-30-layouts">http://www.slideshare.net/senchainc/ext-gwt-30-layouts</a> . Por ejemplo ahora existen un ContentPanel y un FramedPanel y el método setFramed fue removido.</span><br />
<span class="spanish"><br /></span>
<br />
<div class="english">
<b>EXT GWT 2 to GXT3</b><br />
The new GXT3 is going to be more compatible with GWT. Will use system events of GWT, UiBinder support, binding with Editor Framework. For More information you can see the slides of senchacon2011 <a href="http://www.slideshare.net/senchainc/migrating-from-ext-gwt-2x-to-30-10013673">http://www.slideshare.net/senchainc/migrating-from-ext-gwt-2x-to-30-10013673</a> and on Vimeo <a href="http://vimeo.com/33640855">http://vimeo.com/33640855</a>.<br />
Because this is the major upgrade of GXT, some GXT2 components was removed in GXT3 and replaced with GWT components. For example: The FormBinding was replaced by The Editor Framework. GXT2 models have to extend ModelData because is a requirement for data components. The use of ModelData is for get access to object properties because GWT does not support Java Reflection. In GXT3 models are simple POJOS and for get access to object properties use PropertyAccess<T> interface. And The EXT GWT team had to build stores from scratch.<br />
The renderized of GXT2 components was called Lazy Rendered and you couldn't access to DOM in constructor. In GXT3 you could access to DOM in constructor and the renderizer is the same as GWT.<br />
In GXT3 Layouts was modified <a href="http://www.slideshare.net/senchainc/ext-gwt-30-layouts">http://www.slideshare.net/senchainc/ext-gwt-30-layouts</a> . Now we have a ContentPanel and FramedPanel and the method setFramed was removed.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY8OEFqlkncCz4CfcR_PfQsRORdUkGV25CCqVL69VcphCQAeSWD2D2So2pxATl2mYKAyuOmSdyzVm3t6QBnSBV0UAPCljWtUdthGqrrPw3BOynSx3VDsp3NI1JUeNQhJQKQhBl2dqkc40-/s1600/imagen8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="141" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY8OEFqlkncCz4CfcR_PfQsRORdUkGV25CCqVL69VcphCQAeSWD2D2So2pxATl2mYKAyuOmSdyzVm3t6QBnSBV0UAPCljWtUdthGqrrPw3BOynSx3VDsp3NI1JUeNQhJQKQhBl2dqkc40-/s320/imagen8.png" width="320" /></a></div>
<div class="spanish">
Los metodos como setTopComponent y setBottomComponent fueron removidos del ContentPanel<br />
y ahora se utilizara el VerticalLayoutContainer para posicionar los toolbars. <br />
En GXT3 es posible utilizar el <a href="http://code.google.com/intl/es-ES/webtoolkit/doc/latest/DevGuideClientBundle.html">ClientBundle </a>de GWT para optimizar la descarga de tus imágenes y estilos. Por ejemplo ahora todas las imágenes de tu sitio estarán en un paquete de tu código fuente ya no en la carpeta pública. En GXT2 era necesario hacer un link en el html al archivo css de gxt2 y copiar la carpeta resources con las imágenes requeridas a la carpeta pública e tu sitio. Pero en GXT3 gracias al uso del ClientBundle todos los archivos de recursos están incluidos en el jar de GXT.</div>
<div class="english">
The methods like setTopComponent and setBottomComponent were removed and replaced by VerticalLayoutContainer for toolbars.<br />
In GXT3 you can use <a href="http://code.google.com/intl/es-ES/webtoolkit/doc/latest/DevGuideClientBundle.html">ClientBundle </a> of GWT for images and styles. All images should be in a package. And all resources of GXT3 like images and styles are in jar of GXT.</div>
<br />
<div class="spanish">
Adicionalmente ahora GXT3 tiene su propia librería para la generación de gráficos estadísticos <a href="http://www.sencha.com/blog/ext-gwt-3-drawing-and-charting/">http://www.sencha.com/blog/ext-gwt-3-drawing-and-charting/</a> a diferencia de GXT2 que utilizaba una librería de un tercero basado en flash llamado OpenFlashChart.</div>
<div class="english">
GXT3 has a new library for charts <a href="http://www.sencha.com/blog/ext-gwt-3-drawing-and-charting/">http://www.sencha.com/blog/ext-gwt-3-drawing-and-charting/</a>.</div>
<br />
<div class="spanish">
<b>Algunos Inconvenientes en GXT3 ?</b><br />
En GXT2 he utilizado mucho la característica del FormButtonBinding para que el botón guardar de un formulario permaneciera desactivado mientras existan campos inválidos. Pero en GXT3 aún no se si esta característica se mantendra <a href="http://www.sencha.com/forum/showthread.php?177964-FormButtonBinding-is-there-a-replacement">http://www.sencha.com/forum/showthread.php?177964-FormButtonBinding-is-there-a-replacement</a><br />
<br />
<br /></div>
<div class="english">
<b>Some troubles in GXT3?</b><br />
I used FormButtonBinding feature a lot, to make buttons disable while the fields are invalid. But in GXT3 I don't know how can I do that <a href="http://www.sencha.com/forum/showthread.php?177964-FormButtonBinding-is-there-a-replacement">http://www.sencha.com/forum/showthread.php?177964-FormButtonBinding-is-there-a-replacement</a><br />
<b>ExampleRF por dentro</b>
</div>
<div class="english">
<b>ExampleRF in detail</b><br />
<b><br /></b></div>
<div class="spanish">
La aplicación de ejemplo usa AppEngine y Objectify para el almacenamiento de datos y <a href="http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html">RequestFactory</a> para la comunicación con el servidor.</div>
<div class="english">
The example was build using AppEngine and Objectify for persistence and <a href="http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html">RequestFactory</a> for interact with the server side.</div>
<br />
<div class="spanish">
<b>Archivo de Módulo GWT</b> ExampleRF.gwt.xml</div>
<div class="english">
<b>Module file</b> ExampleRF.gwt.xml</div>
<br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='examplerf'>
<inherits name='com.google.gwt.user.User'/>
<inherits name="com.googlecode.objectify.Objectify" />
<inherits name='com.google.web.bindery.requestfactory.RequestFactory' />
<inherits name='com.sencha.gxt.ui.GXT'/>
<inherits name="com.sencha.gwt.uibinder.UiBinder" />
<entry-point class='com.examplerf.client.ExampleRF'/>
<source path='client'/>
<source path='shared'/>
</module></pre>
<br />
<div class="spanish">
Aquí el único mudulo necesario es com.sencha.gxt.ui.GXT adicionalmente necesita de otro módulo com.sencha.gwt.uibinder.UiBinder para poder declarar atributos personalizados en UiBinder según sencha ya no será necesario en GWT 2.5.</div>
<div class="english">
The module needed is com.sencha.gxt.ui.GXT and for custom attributes in UiBinder com.sencha.gwt.uibinder.UiBinder is required and not will need in GWT 2.5</div>
<br />
<div class="spanish">
<b>Archivo html</b> ExampleRF.html</div>
<div class="english">
<b>Html file</b> ExampleRF.html</div>
<br />
<pre class="brush:xml"><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="reset.css">
<link type="text/css" rel="stylesheet" href="ExampleRF.css">
<title>Web Application Starter Project</title>
<script type="text/javascript" language="javascript" src="examplerf/examplerf.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
</body>
</html></pre>
<br />
<div class="spanish">
Aquí mi archivo ExampleRF.css es un archivo en blanco. Según sencha el único archivo de recursos necesario es reset.css
</div>
<div class="english">
ExampleRF.cc is an empty file. And the resource file needed is reset.css</div>
<br />
<pre class="brush:css">/**
* Ext GWT 3.0.0-SNAPSHOT - Ext for GWT
* Copyright(c) 2007-2011, Sencha, Inc.
* licensing@sencha.com
*
* http://sencha.com/license
*/
html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}img,body,html{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul {list-style:none;}caption,th {text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}</pre>
<br />
<div class="spanish">
<b>Mi Clase DAO</b> ColaboradorDao
</div>
<div class="english">
<b>My Class DAO</b> ColaboradorDao
</div>
<br />
<pre class="brush:java">package com.examplerf.server.service;
import java.util.List;
import com.examplerf.server.domain.Colaborador;
import com.examplerf.server.domain.ColaboradorListLoadResultBean;
public class ColaboradorDao extends ObjectifyDao<Colaborador> {
public void save(Colaborador colaborador){
this.put(colaborador);
}
public void remove(Colaborador colaborador){
this.delete(colaborador);
}
public ColaboradorListLoadResultBean list() {
List<Colaborador> list = listAll();
return new ColaboradorListLoadResultBean(list);
}
}</pre>
<div class="spanish">
Aquí la clase de dominio es Colaborador y ColaboradorListLoadResulBean es una clase adicional requerida para poderse mostrar en los componentes de datos de GXT3.
</div>
<div class="english">
The domain class is Colaborador and ColaboradorListLoadResulBean is required for data components.</div>
<br />
Colaborador.java<br />
<pre class="brush:java">package com.examplerf.server.domain;
import com.googlecode.objectify.annotation.Entity;
@Entity
public class Colaborador extends DatastoreObject {
private String nombres;
private String apellidos;
private Integer edad;
public String getNombres() {
return nombres;
}
public void setNombres(String nombres) {
this.nombres = nombres;
}
public String getApellidos() {
return apellidos;
}
public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}
public Integer getEdad() {
return edad;
}
public void setEdad(Integer edad) {
this.edad = edad;
}
}</pre>
ColaboradorListLoadResulBean.java<br />
<pre class="brush:java">package com.examplerf.server.domain;
import java.util.List;
import com.sencha.gxt.data.shared.loader.ListLoadResultBean;
@SuppressWarnings("serial")
public class ColaboradorListLoadResultBean extends ListLoadResultBean<Colaborador> {
public ColaboradorListLoadResultBean(List<Colaborador> list) {
super(list);
}
public ColaboradorListLoadResultBean() {
super();
}
}</pre>
<div class="spanish">
<b>Mi clase RequestContext</b> ColaboradorService</div>
<div class="english">
<b>My class RequestContext</b> ColaboradorService<br />
<br /></div>
<pre class="brush:java">package com.examplerf.shared.service;
import java.util.List;
import com.examplerf.server.domain.ColaboradorListLoadResultBean;
import com.examplerf.server.locator.DaoServiceLocator;
import com.examplerf.server.service.ColaboradorDao;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
import com.sencha.gxt.data.shared.loader.ListLoadResult;
@Service(value = ColaboradorDao.class, locator = DaoServiceLocator.class)
public interface ColaboradorService extends RequestContext {
Request<Void> save(ColaboradorProxy colaborador);
Request<Void> remove(ColaboradorProxy colaborador);
@ProxyFor(value = ColaboradorListLoadResultBean.class)
public interface ColaboradorListLoadResultProxy extends ValueProxy, ListLoadResult<ColaboradorProxy> {
@Override
public List<ColaboradorProxy> getData();
}
Request<ColaboradorListLoadResultProxy> list();
}</pre>
<div class="spanish">
En GWT 2.4 es necesario <a href="http://vivagwt.blogspot.com/2011/09/requestfactory-en-gwt-24.html">validar los RequestContext</a>, cada vez que se modifica este archivo se debe hacer un clean al proyecto <i>Project->Clean</i> . Aquí la unica interfaz especial es ColaboradorListLoadResultProxy y es necesaria para poder llenar el Grid con datos. Nuestro método list() debe retornar objetos de este tipo.
</div>
<div class="english">
RequestContest in GWT 2.4 have to be <a href="http://vivagwt.blogspot.com/2011/09/requestfactory-en-gwt-24.html">validated</a>, every time is modified you have to clean the project <i>Project->Clean</i> . ColaboradorListLoadResultProxy interface is needed for data components.</div>
<br />
<div class="spanish">
<b>Mi Proxy</b> ColaboradorProxy
</div>
<div class="english">
<b>My Proxy</b> ColaboradorProxy
</div>
<br />
<pre class="brush:java">package com.examplerf.shared.proxy;
import com.examplerf.server.domain.Colaborador;
import com.examplerf.server.locator.ObjectifyLocator;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
@ProxyFor(value = Colaborador.class, locator = ObjectifyLocator.class)
public interface ColaboradorProxy extends EntityProxy {
String getNombres();
void setNombres(String nombres);
String getApellidos();
void setApellidos(String apellidos);
Integer getEdad();
void setEdad(Integer edad);
Long getId();
void setId(Long id);
}
</pre>
<div class="spanish">
La interfaz ColaboradorProxy.java representa a la clase de dominio Colaborador.java y sirve para hacer la persistencia desde el cliente. Más información aquí <a href="http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html">http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html</a> .
</div>
<div class="english">
ColaboradorProxy.java interface is like domain class Colaborador.java but in the client side. More about RequestFactory <a href="http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html">http://vivagwt.blogspot.com/2011/09/requestfactory-con-objectify.html</a> .</div>
<b><br /></b>
<br />
<div class="spanish">
<b>Diseñando mi Formulario con UiBinder</b>: ColaboradorEditor.ui.xml
</div>
<div class="english">
<b>Designing my Form with UiBinder</b>: ColaboradorEditor.ui.xml
</div>
<br />
<pre class="brush:xml"><!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
xmlns:form="urn:import:com.sencha.gxt.widget.core.client.form"
xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container"
xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button" >
<ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" />
<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="verticalLayoutData">
<ui:attributes width="1" height="-1" />
</ui:with>
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<gxt:FramedPanel ui:field="form" headerVisible="false" buttonAlign="END" >
<form:FieldSet ui:field="fieldSet" headingText="User Information" collapsible="false" >
<container:VerticalLayoutContainer>
<container:child layoutData="{verticalLayoutData}">
<form:FieldLabel text="First Name">
<form:widget>
<form:TextField ui:field="nombres" allowBlank="false" />
</form:widget>
</form:FieldLabel>
</container:child>
<container:child layoutData="{verticalLayoutData}">
<form:FieldLabel text="Last Name">
<form:widget>
<form:TextField ui:field="apellidos" allowBlank="false" />
</form:widget>
</form:FieldLabel>
</container:child>
<container:child layoutData="{verticalLayoutData}">
<form:FieldLabel text="Age">
<form:widget>
<form:NumberField ui:field="edad" />
</form:widget>
</form:FieldLabel>
</container:child>
</container:VerticalLayoutContainer>
</form:FieldSet>
<gxt:button>
<button:TextButton text="Save" ui:field="save" icon="{images.save}" />
</gxt:button>
<gxt:button>
<button:TextButton text="Cancel" ui:field="cancel" icon="{images.cancel}" />
</gxt:button>
</gxt:FramedPanel>
</ui:UiBinder></pre>
<div class="spanish">
Para Poder usar el FramedPanel es necesario importar el namespace <br />
<pre class="brush:xml">xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"</pre>
igualmente se han importato el resto de namespaces.<br />
Para poder utilizar las imágenes en el código UiBinder es necesario referenciar al ClientBundle con la etiqueta <ui:with><br />
<pre class="brush:xml"><ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" /></pre>
</div>
<div class="english">
For FramedPanel is needed import the namespace <br />
<pre class="brush:xml">xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"</pre>
likewise import the rest of namespaces.<br />
For imáges in ClientBundle and UiBinder is needed put <ui:with><br />
<pre class="brush:xml"><ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" /></pre>
</div>
<br />
<div class="spanish">
Lo siguiente es una forma de declarar los layout data en UiBinder (necesita el jar adicional). También e posible hacerlo por código pero yo prefiero el xml
</div>
<div class="english">
The following code show a way to declare custom attributes like layout data inn UiBinder (aditional jar is required). You could declare layout data in code but I prefer xml
</div>
<br />
<pre class="brush:xml"><ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="verticalLayoutData">
<ui:attributes width="1" height="-1" />
</ui:with></pre>
<br />
<div class="spanish">
<b>El ClientBundle</b> ExampleRFImages.java
</div>
<div class="english">
<b>The ClientBundle</b> ExampleRFImages.java
</div>
<br />
<pre class="brush:java">package com.examplerf.client.images;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
public interface ExampleRFImages extends ClientBundle {
public ExampleRFImages IMAGES = GWT.create(ExampleRFImages.class);
@Source("add.gif")
ImageResource add();
@Source("delete.gif")
ImageResource delete();
@Source("update.png")
ImageResource update();
@Source("save.png")
ImageResource save();
@Source("cancel.png")
ImageResource cancel();
}
</pre>
<div class="spanish">
Las imágenes están en el mismo paquete:
</div>
<div class="english">
The images are in the same package:
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1JRgJWr-fRbtwikJFwhcZOpn4zFOtzM-mOMqPY82BMGdF6bZKCpPvj6fqBUnWvq6FPoZYEqZcA9Zii6eRtMHbBprBB_Zrdk_XBYW6rBoEEEXwiuh1_Aeb5aBoVenoWBzTxQI7JompHtbO/s1600/imagen9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguekz4nuEDaJkdEQrP41HyovPwe_Ajy9qkYJyUc3Ld5WvJkjBhzVCpPexQtY-GK3MCAOScQqqPU2QNa8twtECnfHZTLt1I7F48cmZ_xFet7fSLNzvMa6cXe_dHd-l8Kf7-y2xZgB2jI66f/s1600/imagen10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguekz4nuEDaJkdEQrP41HyovPwe_Ajy9qkYJyUc3Ld5WvJkjBhzVCpPexQtY-GK3MCAOScQqqPU2QNa8twtECnfHZTLt1I7F48cmZ_xFet7fSLNzvMa6cXe_dHd-l8Kf7-y2xZgB2jI66f/s1600/imagen10.png" /></a></div>
<br />
<br />
<div class="spanish">
<b>La Clase Manejadora</b> ColaboradorEditor.java
</div>
<div class="english">
<b>Handler Class</b> ColaboradorEditor.java
</div>
<br />
<pre class="brush:java">package com.examplerf.client;
import com.examplerf.client.events.SaveEvent;
import com.examplerf.client.events.SaveEventHandler;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.FramedPanel;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor;
import com.sencha.gxt.widget.core.client.form.TextField;
public class ColaboradorEditor implements Editor<ColaboradorProxy>, HasHandlers {
private HandlerManager handlerManager;
private static ColaboradorUiBinder uiBinder = GWT.create(ColaboradorUiBinder.class);
interface ColaboradorUiBinder extends UiBinder<Widget, ColaboradorEditor> {
}
@UiField
FramedPanel form;
@UiField
TextField nombres;
@UiField
TextField apellidos;
@UiField(provided = true)
NumberField<Integer> edad;
Window panel;
public ColaboradorEditor() {
handlerManager = new HandlerManager(this);
panel = new Window();
panel.setResizable(false);
edad = new NumberField<Integer>(new NumberPropertyEditor.IntegerPropertyEditor());
//edad.setAllowDecimals(false);
panel.setWidget(uiBinder.createAndBindUi(this));
form.getHeader().setVisible(false);
}
public void show(String title){
panel.setHeadingText(title);
panel.show();
}
@UiHandler("save")
public void onSave(SelectEvent event){
fireEvent(new SaveEvent());
}
@UiHandler("cancel")
public void onCancel(SelectEvent event){
hide();
}
@Override
public void fireEvent(GwtEvent<?> event) {
handlerManager.fireEvent(event);
}
public HandlerRegistration addSaveEventHandler(
SaveEventHandler handler) {
return handlerManager.addHandler(SaveEvent.TYPE, handler);
}
public void clearFields() {
nombres.clearInvalid();
apellidos.clearInvalid();
}
public void hide() {
panel.hide();
}
public boolean isValid() {
boolean n = nombres.isValid();
boolean a = apellidos.isValid();
return n && a;
}
}</pre>
<div class="spanish">
Este Editor esta implementando la interfaz HasHandler para poder enviar eventos personalizados. en este caso el evento SaveEvent. Es importante recordar que si se quiere hacer el binding de un objeto ColaboradorProxy con los campos de texto, estos campos de texto deben existir como variables en el código java. No basta con declarar la caja de texto en UiBinder. Si el TextField nombres sólo se encuentra en el archivo UiBinder y no como variable de clase el GWT Editor no podra hacer el binding.
</div>
<div class="english">
This Editor is immlementing HasHandler interface for send custom events. The event is SaveEvent. Is important remember that Editor Framework need the fields like class attributes. Is not enough put the fields in UiBinder is needed declare the fields like class attributes.</div>
<br />
<pre class="brush:java">@UiField
TextField nombres;</pre>
<pre class="brush:java"> </pre>
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1JRgJWr-fRbtwikJFwhcZOpn4zFOtzM-mOMqPY82BMGdF6bZKCpPvj6fqBUnWvq6FPoZYEqZcA9Zii6eRtMHbBprBB_Zrdk_XBYW6rBoEEEXwiuh1_Aeb5aBoVenoWBzTxQI7JompHtbO/s1600/imagen9.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1JRgJWr-fRbtwikJFwhcZOpn4zFOtzM-mOMqPY82BMGdF6bZKCpPvj6fqBUnWvq6FPoZYEqZcA9Zii6eRtMHbBprBB_Zrdk_XBYW6rBoEEEXwiuh1_Aeb5aBoVenoWBzTxQI7JompHtbO/s1600/imagen9.png" /></a><br />
<div class="spanish">
<b>Resumen de Eventos en GWT:</b>
</div>
<div class="english">
<b>Summary of Events in GWT:</b>
</div>
<br />
<div class="spanish">
Extraido de <a href="http://stackoverflow.com/questions/2951621/gwt-custom-events">http://stackoverflow.com/questions/2951621/gwt-custom-events</a><br />
Los eventos son siempre enviados para informar sobre algo(por ejemplo el cambio de un estado). Los eventos existen en todos los sistemas y frameworks. Para poder enviar y recibir eventos es necesario lo siguiente:
</div>
<div class="english">
Extracted from <a href="http://stackoverflow.com/questions/2951621/gwt-custom-events">http://stackoverflow.com/questions/2951621/gwt-custom-events</a><br />
Events are always sent to inform about something (e.g. a change of state). This is how events work in general in every system or framework (not only in GWT). In order to send and receive events in such systems you have to define:</div>
<div class="spanish">
<ol>
<li>Que es lo que es va a enviar (algun objeto). Esto es opcional.</li>
<li>Quién recibe el evento.</li>
<li>Quién envía el evento.</li>
</ol>
</div>
<div class="english">
<ol>
<li>What is sent (some object). It is not required.</li>
<li>Who receives events (event receivers).</li>
<li>Who sends events (event senders).</li>
</ol>
</div>
<div class="spanish">
<b>Evento SaveEvent</b>
</div>
<div class="english">
<b>Event SaveEvent</b>
</div>
<br />
<div class="spanish">
Este evento se encargara de ejecutar una acción cuando el usuario pulsa en el botón Save. Las clases de eventos los puse en un paquete client.events
</div>
<div class="english">
This event will do something when the user to click in button Save. The events class are in client.events package.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH6GESHN7jwEa8ZYDI8NX_wioiQWs0kROvsE-N4yWUfTbUTAM5dk-6khPf_d3_6RXBT3EZxFvNrQo7tbLlhAMikZQMIlj3NcsmD0erlllJwSTVEqoO2RcNjahyphenhyphenwCs-h9vImrzUKFabD6c_/s1600/imagen11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH6GESHN7jwEa8ZYDI8NX_wioiQWs0kROvsE-N4yWUfTbUTAM5dk-6khPf_d3_6RXBT3EZxFvNrQo7tbLlhAMikZQMIlj3NcsmD0erlllJwSTVEqoO2RcNjahyphenhyphenwCs-h9vImrzUKFabD6c_/s1600/imagen11.png" /></a></div>
<div class="spanish">
<b>La Clase</b> SaveEvent.java
</div>
<div class="english">
<b>Class</b> SaveEvent.java
</div>
<br />
<pre class="brush:java">package com.examplerf.client.events;
import com.google.gwt.event.shared.GwtEvent;
public class SaveEvent extends GwtEvent<SaveEventHandler> {
public static Type<SaveEventHandler> TYPE = new Type<SaveEventHandler>();
@Override
public Type<SaveEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(SaveEventHandler handler) {
handler.onSave(this);
}
}</pre>
<div class="spanish">
Toda clase que representa un evento GWT debe extender GwtEvent esta clase contiene dos metodos abstractos que deben ser implementados <code>getAssociatedType</code> <code>y dispatch</code>.
</div>
<div class="english">
Every class representing a GWT event has to extend GwtEvent class. This class contains two abstract methods which must be implemented: getAssociatedType and dispatch.</div>
<br />
<div class="spanish">
<b>La Interfaz</b> SaveEventHandler.java
</div>
<div class="english">
<b>Interface</b> SaveEventHandler.java
</div>
<br />
<div class="spanish">
En GWT el que recibe el evento es llamado Handler. En este ejemplo la interfaz que recibe el evento es SaveEventHandler.
</div>
<div class="english">
In GWT receivers are called handlers. In the example an event receiver interface will be named SaveEventHandler.</div>
<br />
<pre class="brush:java">package com.examplerf.client.events;
import com.google.gwt.event.shared.EventHandler;
public interface SaveEventHandler extends EventHandler {
void onSave(SaveEvent saveEvent);
}</pre>
<div class="spanish">
Todo Handler debe extender la interfaz EventHandler. También debe definir el método que será llamado cuando el evento ocurra.
</div>
<div class="english">
Each handler has to extend EventHandler interface. It should also define a method which will be invoked when an event occurs.</div>
<br />
<div class="spanish">
<b>Quien envia el evento </b>ColaboradorEditor.java
</div>
<div class="english">
<b>Define event senders</b> ColaboradorEditor.java</div>
<br />
<pre class="brush:java">package com.examplerf.client;
import com.examplerf.client.events.SaveEvent;
import com.examplerf.client.events.SaveEventHandler;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.HasHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.FramedPanel;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor;
import com.sencha.gxt.widget.core.client.form.TextField;
public class ColaboradorEditor implements HasHandlers {
private HandlerManager handlerManager;
public ColaboradorEditor() {
handlerManager = new HandlerManager(this);
}
@UiHandler("save")
public void onSave(SelectEvent event){
fireEvent(new SaveEvent());
}
@Override
public void fireEvent(GwtEvent<?> event) {
handlerManager.fireEvent(event);
}
public HandlerRegistration addSaveEventHandler(
SaveEventHandler handler) {
return handlerManager.addHandler(SaveEvent.TYPE, handler);
}
}</pre>
<div class="spanish">
Todo el que envía un evento debe implementar la interfaz HasHandlers. El elemento más importante aquí es HandlerManager como el nombre lo dice gestiona los Event Handler (manejadores de eventos). Todo evento recibidor que quiere recibir eventos debe registrarse asi mismo como interesado. Para eso son los handler managers. Ellos hacen posible registrar los manejadores de eventos (event handlers) para que puedan enviar un evento en particular a todos los manejadores de eventos registrados.<br />
Cuando un HandlerManager es creado toma un argumento en su constructor. Todo un evento tiene una fuente de origen y este parametro sera usado como origen para todos los eventos enviados por este handler manager en el ejemplo es this como el origen de eventos es ColaboradorEditor.<br />
El metodo fireEvent esta definido en la interfaz HasHandler y es responsable de enviar eventos. Como puede ver sólo usa un handler manager para enviar(fire) un evento.<br />
addSaveEventHandler es usado por todos los recibidores de eventos para registrarse asi mismos como interesados en recibir eventos. De nuevo handler manager es usado para esto.
</div>
<div class="english">
aEvery event sender has to implement HasHandlers interface.<br />
<br />
The most important element here is a HandlerManager field. In GWT HandlerManager as the name suggest manages event handlers (event receivers). As it was said at the beginning every event receiver that wants to receive events must register itself as interested. This is what handler managers are for. They make it possible to register event handlers an they can send a particular event to every registered event handler.<br />
<br />
When a HanlderManager is created it takes one argument in its constructor. Every event has a source of origin and this parameter will be used as a source for all events send by this handler manager. In the example it is this as the source of events is ColaboradorEditor.<br />
<br />
The method fireEvent is defined in HasHandlers interface and is responsible for sending events. As you can see it just uses a handler manager to send (fire) and event.<br />
<br />
addSaveEventHandler is used by event receivers to register themselves as interested in receiving events. Again handler manager is used for this.</div>
<br />
<div class="spanish">
<b>Vincular el recibidor de eventos con el que envía el evento.</b>
</div>
<div class="english">
<b>Bind event receivers with event senders.</b></div>
<br />
<pre class="brush:java">public class ExampleRF implements EntryPoint{
private ColaboradorEditor editor;
public void onModuleLoad() {
editor = new ColaboradorEditor();
editor.addSaveEventHandler(new SaveEventHandler() {
@Override
public void onSave(SaveEvent saveEvent) {
}
});
}
}</pre>
<div class="spanish">
Como parámetro de addSaveEventHandler estoy pasando una clase anónima que es el recibidor de eventos y se registra asi mismo en el enviador de eventos ColaboradorEditor.
</div>
<div class="english">
When everything is defined event receivers must register themselves in event senders. Now all events sent by
ColaboradorEditor will be received by anonymous class.</div>
<br />
<div class="spanish">
<b>Enviar eventos</b>
</div>
<div class="english">
<b>Send events</b><br />
<br /></div>
<div class="spanish">
Para enviar un evento ColaboradorEditor debe crear una instancia de evento y enviarlo usando el método fireEvent.
</div>
<div class="english">
To send an event, ColaboradorEditor must create an event instance and send it using fireEvent method</div>
<br />
<pre class="brush:java"> @UiHandler("save")
public void onSave(SelectEvent event){
fireEvent(new SaveEvent());
}</pre>
<br />
<div class="spanish">
<b>El archivo ExampleRF.ui.xml</b>
</div>
<div class="english">
<b>File ExampleRF.ui.xml</b>
</div>
<br />
<pre class="brush:xml"><!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:gxt="urn:import:com.sencha.gxt.widget.core.client"
xmlns:container="urn:import:com.sencha.gxt.widget.core.client.container"
xmlns:toolbar="urn:import:com.sencha.gxt.widget.core.client.toolbar"
xmlns:button="urn:import:com.sencha.gxt.widget.core.client.button"
xmlns:grid="urn:import:com.sencha.gxt.widget.core.client.grid" >
<ui:with type="com.examplerf.client.images.ExampleRFImages" field="images" />
<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="verticalLayoutData">
<ui:attributes width="1" height="-1" />
</ui:with>
<ui:with type="com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer.VerticalLayoutData" field="centerLayoutData">
<ui:attributes width="1" height="1" />
</ui:with>
<ui:style>
.background {
background-color: white;
}
</ui:style>
<g:VerticalPanel spacing="10">
<gxt:FramedPanel ui:field="panel" collapsible="true" headingText="RequestFactory Grid Example" pixelSize="550, 300">
<container:VerticalLayoutContainer borders="true" addStyleNames="{style.background}">
<container:child layoutData="{verticalLayoutData}">
<toolbar:ToolBar>
<button:TextButton text="Add" ui:field="add" icon="{images.add}" />
<toolbar:SeparatorToolItem />
<button:TextButton text="Edit" ui:field="edit" icon="{images.update}" enabled="false" />
<toolbar:SeparatorToolItem />
<button:TextButton text="Delete" ui:field="delete" icon="{images.delete}" enabled="false" />
<toolbar:FillToolItem />
</toolbar:ToolBar>
</container:child>
<container:child layoutData="{centerLayoutData}" >
<grid:Grid ui:field="grid" />
</container:child>
</container:VerticalLayoutContainer>
</gxt:FramedPanel>
</g:VerticalPanel>
</ui:UiBinder></pre>
<br />
<div class="spanish">
<b>El EntryPoint</b> ExampleRF.java
</div>
<div class="english">
<b>The EntryPoint</b> ExampleRF.java
</div>
<br />
<pre class="brush:java">package com.examplerf.client;
import java.util.ArrayList;
import java.util.List;
import com.examplerf.client.events.SaveEvent;
import com.examplerf.client.events.SaveEventHandler;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.examplerf.shared.service.ColaboradorService;
import com.examplerf.shared.service.ExampleRFRequestFactory;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.gwt.client.RequestFactoryEditorDriver;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.sencha.gxt.core.client.Style.SelectionMode;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.ListStore;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.PropertyAccess;
import com.sencha.gxt.data.shared.loader.ListLoadConfig;
import com.sencha.gxt.data.shared.loader.ListLoadResult;
import com.sencha.gxt.data.shared.loader.ListLoader;
import com.sencha.gxt.data.shared.loader.LoadResultListStoreBinding;
import com.sencha.gxt.data.shared.loader.RequestFactoryProxy;
import com.sencha.gxt.widget.core.client.Dialog;
import com.sencha.gxt.widget.core.client.box.ConfirmMessageBox;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.event.HideEvent;
import com.sencha.gxt.widget.core.client.event.HideEvent.HideHandler;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
import com.sencha.gxt.widget.core.client.info.Info;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent.SelectionChangedHandler;
public class ExampleRF implements EntryPoint, IsWidget {
interface ColaboradorProxyProperties extends PropertyAccess<ColaboradorProxy> {
ModelKeyProvider<ColaboradorProxy> id();
ValueProvider<ColaboradorProxy, String> nombres();
ValueProvider<ColaboradorProxy, String> apellidos();
ValueProvider<ColaboradorProxy, Integer> edad();
}
interface MyUiBinder extends UiBinder<Widget, ExampleRF> {
}
private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class);
private final ExampleRFRequestFactory myRF = GWT.create(ExampleRFRequestFactory.class);
interface Driver extends RequestFactoryEditorDriver<ColaboradorProxy, ColaboradorEditor>{
}
Driver driver = GWT.create(Driver.class);
private ColaboradorEditor editor;
private ColaboradorService cs;
private ColaboradorProxy colaborador;
private ListStore<ColaboradorProxy> store;
private ListLoader<ListLoadConfig, ListLoadResult<ColaboradorProxy>> loader;
@UiField(provided = true)
Grid<ColaboradorProxy> grid;
@UiField
TextButton edit;
@UiField
TextButton delete;
public void onModuleLoad() {
myRF.initialize(new SimpleEventBus());
editor = new ColaboradorEditor();
driver.initialize(myRF, editor);
editor.addSaveEventHandler(new SaveEventHandler() {
@Override
public void onSave(SaveEvent saveEvent) {
RequestContext context = driver.flush();
if(!driver.hasErrors()&&editor.isValid()){
editor.hide();
context.fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
Info.display("ExampleRF", "Se guardo correctamente");
loader.load();
}
});
}
}
});
RootPanel.get().add(this);
}
@Override
public Widget asWidget() {
RequestFactoryProxy<ListLoadConfig, ListLoadResult<ColaboradorProxy>> proxy = new RequestFactoryProxy<ListLoadConfig, ListLoadResult<ColaboradorProxy>>() {
@Override
public void load(ListLoadConfig loadConfig,
Receiver<? super ListLoadResult<ColaboradorProxy>> receiver) {
ColaboradorService cs = myRF.colaboradorService();
cs.list().to(receiver);
cs.fire();
}
};
loader = new ListLoader<ListLoadConfig, ListLoadResult<ColaboradorProxy>>(proxy);
ColaboradorProxyProperties props = GWT.create(ColaboradorProxyProperties.class);
store = new ListStore<ColaboradorProxy>(props.id());
loader.addLoadHandler(new LoadResultListStoreBinding<ListLoadConfig, ColaboradorProxy, ListLoadResult<ColaboradorProxy>>(store));
ColumnConfig<ColaboradorProxy, String> nombresColumn = new ColumnConfig<ColaboradorProxy, String>(props.nombres(), 150, "Nombres");
ColumnConfig<ColaboradorProxy, String> apellidosColumn = new ColumnConfig<ColaboradorProxy, String>(props.apellidos(), 150, "Apellidos");
ColumnConfig<ColaboradorProxy, Integer> edadColumn = new ColumnConfig<ColaboradorProxy, Integer>(props.edad(), 80, "Edad");
List<ColumnConfig<ColaboradorProxy, ?>> l = new ArrayList<ColumnConfig<ColaboradorProxy, ?>>();
l.add(nombresColumn);
l.add(apellidosColumn);
l.add(edadColumn);
ColumnModel<ColaboradorProxy> cm = new ColumnModel<ColaboradorProxy>(l);
grid = new Grid<ColaboradorProxy>(store, cm) {
@Override
protected void onAfterFirstAttach() {
super.onAfterFirstAttach();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
@Override
public void execute() {
loader.load();
}
});
}
};
grid.setLoader(loader);
grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
grid.getSelectionModel().addSelectionChangedHandler(new SelectionChangedHandler<ColaboradorProxy>() {
@Override
public void onSelectionChanged(
SelectionChangedEvent<ColaboradorProxy> event) {
int size = event.getSelection().size();
if(size == 0){
edit.setEnabled(false);
delete.setEnabled(false);
}else if(size == 1){
edit.setEnabled(true);
delete.setEnabled(true);
}else if(size > 1){
edit.setEnabled(false);
delete.setEnabled(true);
}
}
});
return uiBinder.createAndBindUi(this);
}
@UiHandler("add")
public void onAdd(SelectEvent event){
cs = myRF.colaboradorService();
colaborador = cs.create(ColaboradorProxy.class);
cs.save(colaborador);
driver.edit(colaborador, cs);
editor.clearFields();
editor.show("Nuevo Colaborador");
}
@UiHandler("edit")
public void onEdit(SelectEvent event){
cs = myRF.colaboradorService();
colaborador = grid.getSelectionModel().getSelectedItem();
cs.save(colaborador);
driver.edit(colaborador, cs);
editor.clearFields();
editor.show("Editar Colaborador");
}
@UiHandler("delete")
public void onDelete(SelectEvent event){
ConfirmMessageBox box = new ConfirmMessageBox("ExampleRF", "Esta seguro que desea eliminar?");
box.addHideHandler(new HideHandler() {
@Override
public void onHide(HideEvent event) {
Dialog btn = (Dialog) event.getSource();
if("Yes".equals(btn.getHideButton().getText())){
cs = myRF.colaboradorService();
colaborador = grid.getSelectionModel().getSelectedItem();
cs.remove(colaborador).fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
Info.display("ExampleRF", "Se elimino correctamente");
loader.load();
}
});
}
}
});
box.show();
}
}</pre>
<div class="spanish">
Eso es todo por hoy espero les sea de ayuda.
</div>
<div class="english">
That's all for now, I hope it helps someone
</div>
Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com2tag:blogger.com,1999:blog-7772385331860770062.post-34899330697277959272011-09-12T15:42:00.000-07:002016-02-05T11:54:55.535-08:00RequestFactory in GWT 2.4<div class="spanish">
El codigo está disponible en GitHub usa GWT 2.4 y AppEngine 1.7.0
</div>
<div class="english">
The code is available in GitHub using GWT 2.4 y AppEngine 1.7.0
</div>
<a href="https://github.com/poseidonjm/GAE-Simple">https://github.com/poseidonjm/GAE-Simple</a><br />
<br />
<a name='more'></a><br />
<div class="spanish">
En un post anterior hice una demostración de <a href="http://rhemsolutions.blogspot.com/2011/09/requestfactory-con-objectify.html">RequestFactory con Objectify</a> utilizando GWT 2.3 basándome en el blog de <a href="http://turbomanage.wordpress.com/2011/03/25/using-gwt-requestfactory-with-objectify/">David M. Chandler</a>. Pero cuando quise actualizar mi proyecto a GWT 2.4 versión disponible a la fecha ya no funcionaba. De acuerdo a <a href="http://code.google.com/p/google-web-toolkit/wiki/RequestFactoryInterfaceValidation">RequestFactoryInterfaceValidation</a> A partir de GWT 2.4 las Interfaces RequestFactory debe ser validadas antes de ser usadas por el código RequestFactory del server. Para lo cual necesita <a href="http://search.maven.org/remotecontent?filepath=com/google/web/bindery/requestfactory-apt/2.4.0/requestfactory-apt-2.4.0.jar">requestfactory-apt.jar</a> que es el que realiza la validación. este jar lo descargue y lo puse en un directorio GWT_TOOLS/requestfactory-apt.jar
</div>
<div class="english">
In a previous post I made an example with <a href="http://rhemsolutions.blogspot.com/2011/09/requestfactory-con-objectify.html">RequestFactory and Objectify</a> using GWT 2.3 following the guide lines of <a href="http://turbomanage.wordpress.com/2011/03/25/using-gwt-requestfactory-with-objectify/">David M. Chandler</a>. But when I wanted to use GWT 2.4 my example didn't work. According <a href="http://code.google.com/p/google-web-toolkit/wiki/RequestFactoryInterfaceValidation">RequestFactoryInterfaceValidation</a> starting with GWT 2.4, RequestFactory interfaces must be validated before they can be used by the RequestFactory server code. Then I download <a href="http://search.maven.org/remotecontent?filepath=com/google/web/bindery/requestfactory-apt/2.4.0/requestfactory-apt-2.4.0.jar">requestfactory-apt.jar</a> for validation and put in a directory GWT_TOOLS/requestfactory-apt.jar.</div>
<br />
<div class="spanish">
A continuación voy a actualizar ExampleRF de la versión GWT 2.3 a GWT 2.4
</div>
<div class="english">
I am going to update ExampleRF from GWT 2.3 to GWT 2.4</div>
<br />
<div class="spanish">
<b>Agregar el SDK de GWT 2.4 a Eclipse IDE</b>
</div>
<div class="english">
<b>Add GWT 2.4 SDK in Eclipse</b></div>
<br />
<div class="spanish">
El GWT 2.4 lo pueden descargar <a href="http://google-web-toolkit.googlecode.com/files/gwt-2.4.0.zip">aqui</a>. Luego extraigo el zip.<br />
Ahora para agregar un nuevo GWT SDK al Eclipse IDE hay que ir a Window->Preferences->Google->Web Toolkit
</div>
<div class="english">
Download GWT 2.4 from <a href="http://google-web-toolkit.googlecode.com/files/gwt-2.4.0.zip">here</a>. Extract zip file. And for add a new GWT SDK in Eclipse IDE go to Window->Preferences->Google->Web Toolkit</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcFUkdx3a4lMDzUlfFpqrXd7JUPUIgLowZntIsKkdLIPvkbUnYVi3swPkNn6rgDyJUdkPiVamOGI3hvUFcbedmSNJddVTVrHQBsDCSMar8ZnNRbMO-O9MZqXie6BuFFWWO3jtCkidBzjWk/s1600/7-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="279" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcFUkdx3a4lMDzUlfFpqrXd7JUPUIgLowZntIsKkdLIPvkbUnYVi3swPkNn6rgDyJUdkPiVamOGI3hvUFcbedmSNJddVTVrHQBsDCSMar8ZnNRbMO-O9MZqXie6BuFFWWO3jtCkidBzjWk/s320/7-1.png" width="320" /></a></div>
<br />
<div class="spanish">
Ahora descargo <a href="http://www.2shared.com/file/cDedheRb/ExampleRF.html">ExampleRF</a> y lo extraigo en un directorio.
</div>
<div class="english">
Download <a href="http://www.2shared.com/file/cDedheRb/ExampleRF.html">ExampleRF</a> and extract in a directory.</div>
<br />
<div class="spanish">
Ahora voy a Eclipse IDE e importo el proyecto. Hago click derecho en el explorador de proyectos y del menú contextual selecciono Import.</div>
<div class="english">
Open Eclipse IDE for import the project. Right click on package explorer in context menu. Select Import.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ1x74GX0Q-2jPEFnvPPkHO6rUidGvIjO6aLzYaKwE7Q3lSgtUopH6kOnP6ShtxjEW0r5IWDyNCHk_2VaYuQN9dFF85dAeBBl5nkV4SJUrLP13SQPY67wPDQkoHf_eJ3HkxbasQQDuY65p/s1600/7-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="316" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ1x74GX0Q-2jPEFnvPPkHO6rUidGvIjO6aLzYaKwE7Q3lSgtUopH6kOnP6ShtxjEW0r5IWDyNCHk_2VaYuQN9dFF85dAeBBl5nkV4SJUrLP13SQPY67wPDQkoHf_eJ3HkxbasQQDuY65p/s320/7-2.png" width="320" /></a></div>
<div class="spanish">
De la ventana Import selecciono Existing Projects Into Workspace y le doy Next.
</div>
<div class="english">
In Import dialog select Existing Projects Into Workspace and click Next.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEdzwy7B-sJgmYMSyewONV_BOp3TRqM1G5aQNPj0SvmuWqy2UZiGXVf9mYJS4q5wALqJ5WvZ6ORO7jM3fmasdAm3WoV_PBM3fFg-6-8b9e8vPBF8YiPupyCUHUlMQ8Lo8egWEp2BFEVSnV/s1600/7-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgEdzwy7B-sJgmYMSyewONV_BOp3TRqM1G5aQNPj0SvmuWqy2UZiGXVf9mYJS4q5wALqJ5WvZ6ORO7jM3fmasdAm3WoV_PBM3fFg-6-8b9e8vPBF8YiPupyCUHUlMQ8Lo8egWEp2BFEVSnV/s320/7-3.png" width="305" /></a></div>
<div class="spanish">
En la siguiente vista le doy click al botón Browse y busco el proyecto ExampleRF y le doy Finish.
</div>
<div class="english">
In the next dialog click Browse, select ExampleRF and click Finish.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMKI46YgakFCTOgSwcMmnXHCy2C0FVlECF6F4gXMhY4UWhC9fFm37ovItvDEfRnH0vLTwoSvJJwcJg4jMyAn8VxJGVNosjzCTS5NLPkF9O5e9E0KSEvw3Lj8tPHsSttcnbOvJG6ZQwqdc4/s1600/7-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMKI46YgakFCTOgSwcMmnXHCy2C0FVlECF6F4gXMhY4UWhC9fFm37ovItvDEfRnH0vLTwoSvJJwcJg4jMyAn8VxJGVNosjzCTS5NLPkF9O5e9E0KSEvw3Lj8tPHsSttcnbOvJG6ZQwqdc4/s320/7-4.png" width="303" /></a></div>
<div class="spanish">
<div class="separator" style="clear: both; text-align: left;">
La versión que voy a utilizar ahora es GWT 2.4.</div>
<div class="separator" style="clear: both; text-align: left;">
Hago click derecho en el proyecto y del menú contextual selecciono Properties. Luego en la ventana Properties voy a Google -> Web Toolkit</div>
</div>
<div class="english">
I will use GWT 2.4.<br />
Right click on the project in context menu select Properties. In Properties dialog <span style="text-align: left;">Google -> Web Toolkit.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUFG-jzo2bkMXqnRUboSok84uYs4HFw-CzYmbBYwr9gX7GdkMyUZdhWq2SgAdTyUwGUo5QvhcQt8nxfXpyphhxx7Gel43sixymQ4pKFXpMGaBCyFJFaniIUc7ewgjY89tWpPt3jt5BESjk/s1600/7-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUFG-jzo2bkMXqnRUboSok84uYs4HFw-CzYmbBYwr9gX7GdkMyUZdhWq2SgAdTyUwGUo5QvhcQt8nxfXpyphhxx7Gel43sixymQ4pKFXpMGaBCyFJFaniIUc7ewgjY89tWpPt3jt5BESjk/s320/7-5.png" width="320" /></a></div>
<div class="spanish">
<div class="separator" style="clear: both; text-align: left;">
Ahora voy a tratar de ejecutar el proyecto le doy click derecho y voy a Run As -> Web Application</div>
<div class="separator" style="clear: both; text-align: left;">
y me muestra los siguientes errores.</div>
<div class="separator" style="clear: both; text-align: left;">
En Console</div>
</div>
<div class="english">
I will try to run the project. Right click on the project and go to <span style="text-align: left;">Run As -> Web Application. The Console output shows the following errors</span></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: left;">
[ERROR] Unexpected error</div>
<div class="separator" style="clear: both; text-align: left;">
java.lang.RuntimeException: The RequestFactory ValidationTool must be run for the com.examplerf.shared.service.ExampleRFRequestFactory RequestFactory type</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.vm.impl.Deobfuscator$Builder.load(Deobfuscator.java:59)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.ResolverServiceLayer.updateDeobfuscator(ResolverServiceLayer.java:43)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.ResolverServiceLayer.resolveRequestFactory(ResolverServiceLayer.java:176)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.resolveRequestFactory(ServiceLayerDecorator.java:172)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.resolveRequestFactory(ServiceLayerDecorator.java:172)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.ServiceLayerDecorator.resolveRequestFactory(ServiceLayerDecorator.java:172)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at java.lang.reflect.Method.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:100)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.ServiceLayerCache.getOrCache(ServiceLayerCache.java:233)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.ServiceLayerCache.resolveRequestFactory(ServiceLayerCache.java:198)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:207)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:127)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.web.bindery.requestfactory.server.RequestFactoryServlet.doPost(RequestFactoryServlet.java:133)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:58)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:351)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.Server.handle(Server.java:326)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="spanish">
<div class="separator" style="clear: both; text-align: left;">
y en el Development mode</div>
</div>
<div class="english">
Development mode output</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: left;">
17:24:37.530 [ERROR] [examplerf] Uncaught exception escaped</div>
<div class="separator" style="clear: both; text-align: left;">
com.google.web.bindery.event.shared.UmbrellaException: One or more exceptions caught, see full set in UmbrellaException#getCauses</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.fail(AbstractRequestContext.java:727)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$5.onTransportFailure(AbstractRequestContext.java:1104)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport$1.onResponseReceived(DefaultRequestTransport.java:140)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at java.lang.reflect.Method.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.core.client.impl.Impl.apply(Impl.java)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:213)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at java.lang.reflect.Method.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)</div>
<div class="separator" style="clear: both; text-align: left;">
at java.lang.Thread.run(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
Caused by: java.lang.RuntimeException: Server Error 500 <html></div>
<div class="separator" style="clear: both; text-align: left;">
<head></div>
<div class="separator" style="clear: both; text-align: left;">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/></div>
<div class="separator" style="clear: both; text-align: left;">
<title>Error 500 INTERNAL_SERVER_ERROR</title></div>
<div class="separator" style="clear: both; text-align: left;">
</head></div>
<div class="separator" style="clear: both; text-align: left;">
<body><h2>HTTP ERROR 500</h2></div>
<div class="separator" style="clear: both; text-align: left;">
<p>Problem accessing /gwtRequest. Reason:</div>
<div class="separator" style="clear: both; text-align: left;">
<pre> INTERNAL_SERVER_ERROR</pre></p><hr /><i><small>Powered by Jetty://</small></i><br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
<br/> </div>
<div class="separator" style="clear: both; text-align: left;">
</body></div>
<div class="separator" style="clear: both; text-align: left;">
</html></div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.shared.Receiver.onFailure(Receiver.java:44)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequest.onFail(AbstractRequest.java:118)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext.fail(AbstractRequestContext.java:707)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.shared.impl.AbstractRequestContext$5.onTransportFailure(AbstractRequestContext.java:1104)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport$1.onResponseReceived(DefaultRequestTransport.java:140)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at java.lang.reflect.Method.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.core.client.impl.Impl.apply(Impl.java)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:213)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at java.lang.reflect.Method.invoke(Unknown Source)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)</div>
<div class="separator" style="clear: both; text-align: left;">
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)</div>
<div class="separator" style="clear: both; text-align: left;">
at java.lang.Thread.run(Unknown Source)</div>
<br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="spanish">
<div class="separator" style="clear: both; text-align: left;">
Ahora voy a configurar el requestfactory-apt.jar en Eclipse IDE.</div>
<div class="separator" style="clear: both; text-align: left;">
Le doy click derecho al proyecto voy a Properties de la ventana siguiente voy a Java Compiler->Annotation Processing</div>
</div>
<div class="english">
I will configure <span style="text-align: left;">requestfactory-apt.jar in Eclipse IDE. Right click on project in context menu select Properties and go to </span><span style="text-align: left;">Java Compiler->Annotation Processing</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpOqlLduGGaXGaKSienppkeIvoX1JCKKXfxmxEzICWB2i2BFwB-yyhvX_b7Kun6beQUZPCvG4lqsgXwUl8ZiXkF1P5_Jv-aGPQWOk9XqSYnEO-WVftUcU3Xg-3vrF4IXkp7H9FB-crS6DV/s1600/7-6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpOqlLduGGaXGaKSienppkeIvoX1JCKKXfxmxEzICWB2i2BFwB-yyhvX_b7Kun6beQUZPCvG4lqsgXwUl8ZiXkF1P5_Jv-aGPQWOk9XqSYnEO-WVftUcU3Xg-3vrF4IXkp7H9FB-crS6DV/s320/7-6.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="spanish">
Luego en Java Compiler->Annotation Processing->Factory Path agrego el requestfactory-apt.jar<br />
Le doy al botón Add External JARS y agrego el jar.
</div>
<div class="english">
Go to Java Compiler->Annotation Processing->Factory Path click on Add External JARS for add requestfactory-apt.jar</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn5m01oz2Jbi9aaGIvCHBnkDf_Q6slbENjpKqz4GDKOkoEYN4sR_8sxOZ4um7Aqq73HbqAa8xG6WqxWjxQiyoxnopQly9sNHhAl8A7z9-Jj4CeUEFvoIzj6f56BjDAm9BbSd0CXHLz9s0n/s1600/7-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="259" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn5m01oz2Jbi9aaGIvCHBnkDf_Q6slbENjpKqz4GDKOkoEYN4sR_8sxOZ4um7Aqq73HbqAa8xG6WqxWjxQiyoxnopQly9sNHhAl8A7z9-Jj4CeUEFvoIzj6f56BjDAm9BbSd0CXHLz9s0n/s320/7-7.png" width="320" /></a></div>
<div class="spanish">
A los dos mensajes que aparecen a continuación les doy Yes.
</div>
<div class="english">
In the following two dialogs, click on Yes</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ7kgl6P348MRHaYStTw30mAQuiuCGvoiHdgDJJhnfwwSIxUcRbKMo4eNte7-6XnvV5n0C-e8tDKrQwqwAmmu68bJHN9tCa_ZYgTsXdIU9dXVdhTGvh7tBjXmP1huT2f-2JQ3hqSzfNrH1/s1600/7-8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<br />
<div class="spanish">
Cada vez que cambio el RequestContext debo hacer un rebuild al proyecto para revalidar
</div>
<div class="english">
Everytime RequestContext is modified you need rebuild the project for revalidate</div>
<br />
<div class="spanish">
Selecciono el proyecto, Luego voy a Project->Clean...
</div>
<div class="english">
Select the project, and go to Project->Clean...</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimnA5rfSyltl-yVJc6GlmhUhJKkBXsmpyZWrQQvVyPpnZZdtl67GuGXrd9W1VglpBQsyGt6b2CoJpxSRGF66jXBkOmaIUZeDG7YV2byQ1bgXJLrOXGzxeylpby-GkaMFfcJmm_1Aaptjgt/s1600/imagen4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimnA5rfSyltl-yVJc6GlmhUhJKkBXsmpyZWrQQvVyPpnZZdtl67GuGXrd9W1VglpBQsyGt6b2CoJpxSRGF66jXBkOmaIUZeDG7YV2byQ1bgXJLrOXGzxeylpby-GkaMFfcJmm_1Aaptjgt/s320/imagen4.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi217m4RruZFxCaHFkF8mQk7XAFWemXxZU4oCvPnK9ujhND6mQfjRPOJd2XwgJCVoLK4z8XfcsxCR0l5bNTm_8iGUGtBznm5B1-6ytiBkz41t9ft-KaduRowfh0_p4Vq-6kFsVcNrmMT7b4/s1600/imagen5.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="239" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi217m4RruZFxCaHFkF8mQk7XAFWemXxZU4oCvPnK9ujhND6mQfjRPOJd2XwgJCVoLK4z8XfcsxCR0l5bNTm_8iGUGtBznm5B1-6ytiBkz41t9ft-KaduRowfh0_p4Vq-6kFsVcNrmMT7b4/s320/imagen5.png" width="320" /></a></div>
<br />
<div class="spanish">
Ahora voy a ejecutar el proyecto y ahora esta todo OK.
</div>
<div class="english">
I run the project and everything is OK.</div>
<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ7kgl6P348MRHaYStTw30mAQuiuCGvoiHdgDJJhnfwwSIxUcRbKMo4eNte7-6XnvV5n0C-e8tDKrQwqwAmmu68bJHN9tCa_ZYgTsXdIU9dXVdhTGvh7tBjXmP1huT2f-2JQ3hqSzfNrH1/s1600/7-8.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="147" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZ7kgl6P348MRHaYStTw30mAQuiuCGvoiHdgDJJhnfwwSIxUcRbKMo4eNte7-6XnvV5n0C-e8tDKrQwqwAmmu68bJHN9tCa_ZYgTsXdIU9dXVdhTGvh7tBjXmP1huT2f-2JQ3hqSzfNrH1/s320/7-8.png" width="320" /></a> <br />
<br />Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com2tag:blogger.com,1999:blog-7772385331860770062.post-69880429806808907372011-09-09T19:12:00.000-07:002016-02-12T17:50:12.676-08:00GWT EditorEl <a href="http://code.google.com/intl/es-ES/webtoolkit/doc/latest/DevGuideUiEditors.html">GWT Editor framework</a> es un componente de Google Web Toolkit disponible a partir de la versión 2.1 que te permite de forma fácil enviar los datos de tus objetos del código a la interfaz de usuario y viceverza. Es decir hacer el vínculo de datos o data binding. Estuve probando un ejemplo sencillo del blog de <a href="http://onthejvm.com/gwt-data-bindings-first-look">Arthur Kalmenson</a> CustomerDemo que muestra el uso del GWT Editor sin hacer uso de persistencia el código que recopilé ligeramente modificado pueden descargarlo <a href="http://www.2shared.com/file/U_xJZkJS/CustomerDemo.html">aquí</a>.<br />
A continuación voy a explicar un poco el ejemplo.<br />
<br />
<a name='more'></a><br />
Empezando por la lista de archivos.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWQZOX-QeI_EpP9YHhfnwcCeklAGx00yVaQKFaa6e-K-IsWRCXPTUd8XEDyqK4QMhNmKykgQ4p_PBqhHPsHnM8uQDB15pOt94y3pfQPSiUUTnXsTCi3x4JYNiDYxKcVXF4LrRyoGZOF-Rl/s1600/6-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="259" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWQZOX-QeI_EpP9YHhfnwcCeklAGx00yVaQKFaa6e-K-IsWRCXPTUd8XEDyqK4QMhNmKykgQ4p_PBqhHPsHnM8uQDB15pOt94y3pfQPSiUUTnXsTCi3x4JYNiDYxKcVXF4LrRyoGZOF-Rl/s320/6-1.png" width="320" /></a></div>
CustomerDemo.java es el entry point o archivo de entrada de la aplicación y su método es el onModuleLoad() es como el void main() en java estandar.<br />
Los archivos UiBinder EmailEditor.ui.xml y su clase manejadora EmailEditor.java los creé con el asistente New->UiBinder del GPE(Google Plugin for Eclipse), igualmente con los archivos CustomerEditor.ui.xml y CustomerEditor.java.<br />
Las clases Customer.java y Email.java son simples POJO(Plain Old Java Object) files. Es decir no contienen código adicional además de sus propiedades y metodos. En Eclipse IDE una vez digitado las propiedades se pueden generar los métodos getters y setters haciendo click derecho en el código fuente y seleccionar del menú contextual Source->Generate Getters and Setters...<br />
<br />
<b>La clase Customer.java</b><br />
<pre class="brush:java">public class Customer {
private String firstName, lastName;
private Email email;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
}
</pre>
Como puede notar una propiedad del bean(así se les llama a las clases POJO) Customer es email un objeto de la clase Email. En este ejemplo no se usa la persistencia(uso de un almacén de datos). Pero este bean podría almacenarse perfectamente en el DataStore del AppEngine(El servicio de alojamiento de aplicaciones de Google o servicio de hosting) el DataStore usa <a href="http://es.wikipedia.org/wiki/BigTable">BigTable </a>un almacen de datos NoSql es decir no relacional. Se puede pensar en que tus datos son almacenados en HashMaps dentro de HashMaps.Por tanto la clase Customer puede almacenar tipos primitivos como String hasta objetos embebidos como Email.<br />
<br />
<b>Los archivos EmailEditor.java y EmailEditor.ui.xml</b><br />
Es el par de archivos necesarios para utilizar <a href="http://uibinder/">UiBinder</a>. En GWT es posible definir las vistas de mi aplicación utilizando código Java al estilo del Java Swing. Pero los desarrolladores web estamos acostumbrados a utilizar HTML y CSS para definir nuestras vistas de aplicación. UiBinder Permite mezclar HTML y Widgets GWT y permite el uso de hojas de estilo. Al mismo tiempo se logra una separación entre el código que define la interfaz(EmailEditor.ui.xml) y la lógica de aplicación(EmailEditor.java).<br />
<pre class="brush:java">package com.customerdemo.client;
import com.customerdemo.shared.Email;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
public class EmailEditor extends Composite implements Editor<Email> {
private static EmailEditorUiBinder uiBinder = GWT
.create(EmailEditorUiBinder.class);
interface EmailEditorUiBinder extends UiBinder<Widget, EmailEditor> {
}
@UiField
TextBox email;
public EmailEditor() {
initWidget(uiBinder.createAndBindUi(this));
}
}</pre>
<pre class="brush:xml"><!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
</ui:style>
<g:HTMLPanel>
<div>
Email:
<g:TextBox ui:field="email" />
</div>
</g:HTMLPanel>
</ui:UiBinder>
</pre>
Esta clase manejadora implementa la interfaz parametrizada Editor<T> e indica que <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">EmailEditor </span>es un widget bindable(vinculable) con la clase Email.<br />
En el constructor <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">EmailEditor()</span> es donde se carga e inicializa la interfaz.<br />
Los widgets GWT tienen el prefijo <g: como <span class="Apple-style-span" style="font-family: monospace; white-space: pre;"><g:HTMLPanel></span> y <span class="Apple-style-span" style="font-family: monospace; white-space: pre;"><g:TextBox ui:field="email" /></span> para poder usar el TextBox en la aplicación es necesario incluirlo en la clasae manejadora <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">EmailEditor </span> como atributo.<br />
<br />
<pre class="brush:java">@UiField
TextBox email;</pre>
<br />
La anotación <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">@UiField</span> indica que el widget se encuentra en su respectivo archivo UiBinder EmailEditor.ui.xml. <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">TextBox email</span> Indica que es un TextBox y que tiene como atributo <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">ui:field="email"</span> .Este atributo ui:field es el que se utiliza para vincular los widgets del UiBinder con el código Java de su clase manejadora.<br />
La clase <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">EmailEditor </span>es un widget personalizado que puede hacer uso de los beneficios del GWT Editor.<br />
<br />
<b>Los archivos CustomerEditor.java y CustomerEditor.ui.xml</b><br />
<pre class="brush:java">package com.customerdemo.client;
import com.customerdemo.shared.Customer;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
public class CustomerEditor extends Composite implements Editor<Customer> {
private static CustomerEditorUiBinder uiBinder = GWT
.create(CustomerEditorUiBinder.class);
interface CustomerEditorUiBinder extends UiBinder<Widget, CustomerEditor> {
}
@UiField
TextBox firstName;
@UiField
TextBox lastName;
@UiField
EmailEditor emailEditor;
public CustomerEditor() {
initWidget(uiBinder.createAndBindUi(this));
}
}</pre>
<pre class="brush:xml"><!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:d="urn:import:com.customerdemo.client">
<ui:style>
</ui:style>
<g:HTMLPanel>
<h3>Customer</h3>
<div>
First Name:
<g:TextBox ui:field="firstName" />
</div>
<div>
Last Name:
<g:TextBox ui:field="lastName" />
</div>
<div>
<d:EmailEditor ui:field="emailEditor" />
</div>
</g:HTMLPanel>
</ui:UiBinder></pre>
La única diferencia con el anterior es que aquí esta haciendo uso el widget personalizado <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">EmailEditor </span> para poder incluirlo en el archivo UiBinder es necesario importar el paquete donde se encuentra haciendo uso de un namespace <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">xmlns:d="urn:import:com.customerdemo.client"</span>. Esto indica que los widgets personalizados estan en el paquete <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">com.customerdemo.client</span> y <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">xmlns:d </span>indica que voy a acceder a los widgets por medio del prefijo <d: en este caso <span class="Apple-style-span" style="font-family: monospace; white-space: pre;"><d:EmailEditor ui:field="emailEditor" /></span> .<br />
<br />
<b>El entry point CustomerDemo.java</b><br />
<br />
<pre class="brush:java">package com.customerdemo.client;
import com.customerdemo.shared.Customer;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootPanel;
public class CustomerDemo implements EntryPoint {
interface Driver extends SimpleBeanEditorDriver<Customer, CustomerEditor> {
}
Driver driver = GWT.create(Driver.class);
public void onModuleLoad() {
CustomerEditor editor = new CustomerEditor();
driver.initialize(editor);
driver.edit(new Customer());
RootPanel.get().add(editor);
Button button = new Button("Get Data");
RootPanel.get().add(button);
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent arg0) {
Customer customer = driver.flush();
Window.alert("first name: "
+ customer.getFirstName() + ", last name: "
+ customer.getLastName());
}
});
}
}</pre>
Para decirle a la aplicación que este archivo es el archivo de arranque debe implementar la interfaz <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">EntryPoint</span> . El GWT Editor utiliza clases Driver para vincular un POJO con su vista o un bean con su editor. Estas clases son <span class="Apple-style-span" style="background-color: white; font-family: "helvetica" , "arial" , sans-serif; font-size: x-small; line-height: 16px;"><code style="color: #007000; font-family: monospace; font-size: 10pt;">SimpleBeanEditorDriver</code></span><span class="Apple-style-span" style="background-color: white; font-family: "helvetica" , "arial" , sans-serif; font-size: x-small; line-height: 16px;"> y </span><span class="Apple-style-span" style="background-color: white; color: #007000; font-family: monospace; font-size: 13px; line-height: 16px;">RequestFactoryEditorDriver</span>. El botón se ha creado utilizando código java y se le agregó un evento onClick. La vista y el botón se agregó al cuerpo de la página web haciendo uso de <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">RootPanel.get()</span> que te devuelve el <body> de la página. Dentro del evento obtengo los datos ingresados llamando al método flush() del Driver.<br />
<br />
<b>El archivo de módulo CustomerDemo.gwt.xml</b><br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='customerdemo'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<entry-point class='com.customerdemo.client.CustomerDemo'/>
<source path='client'/>
<source path='shared'/>
</module></pre>
En este archivo xml se indica los módulos que utilizará nuestra aplicación. Un módulo es una librería diseñado exclusivamente para su uso dentro de GWT. Aquí también le indico a mi aplicación donde está mi archivo de arranque o entry point. Además se indica los paquetes que se traducirán a Javascript que son el client y shared. El paquete shared se llama así porque su contenido es utilizado por el cliente (Javascript) y el servidor(Java).<br />
<br />
<b>El archivo web.xml</b><br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>CustomerDemo.html</welcome-file>
</welcome-file-list>
</web-app></pre>
<br />
Como toda aplicación web Java aquí es donde es definen los servlets y la página por defecto CustomerDemo.html y otras configuraciones.Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com0tag:blogger.com,1999:blog-7772385331860770062.post-61898964585593214942011-09-07T09:47:00.000-07:002016-02-12T17:50:31.709-08:00RequestFactory con ObjectifyA partir de GWT 2.1 RequestFactory es la nueva forma de comunicación con el servidor. Para los programadores Java, GWT ofrece maneras mas fáciles de interactuar con el servidor como son el RPC(Remote Procedure Call) y RequestFactory.<br />
<a href="http://code.google.com/p/objectify-appengine/">Objectify </a>es la librería mas conveniente para acceder al Datastore de AppEngine el servicio de alojamiento de aplicaciones de Google. El AppEngine usa BigTable un almacen de datos NoSql.<br />
<br />
<a name='more'></a><br /><br />
Para implementar la persistencia es necesario instalar el AppEngine SDK en un anterior post instale el <a href="http://rhemsolutions.blogspot.com/2011/08/instalar-eclipse-y-gwt.html">Plugin de Google para Eclipse</a>.<br />
El codigo fuente de ejemplo lo puede descargar en este <a href="http://www.2shared.com/file/cDedheRb/ExampleRF.html">enlace</a>.<br />
Voy a la dirección <a href="http://code.google.com/intl/es-ES/appengine/downloads.html">http://code.google.com/intl/es-ES/appengine/downloads.html</a> y descargo appengine-java-sdk-1.5.3.zip lo extraigo en un directorio y ejecuto el Eclipse IDE voy al menu Window->Preferences->Google->App Engine y agrego la ruta del SDK.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxzcOk5OOefFUgr0ape22XyUrllBL5qiZtVwznJ6s1CvSoB0RXh9h_3ZIYbCDloSgMCrVm5Tm56jBT8ncAIC1g05xFRVTcZnU_wCiXk1HB49_zH_dW4ZjRb985iYS5wXhcmoTK7w5fLS-I/s1600/5-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="279" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxzcOk5OOefFUgr0ape22XyUrllBL5qiZtVwznJ6s1CvSoB0RXh9h_3ZIYbCDloSgMCrVm5Tm56jBT8ncAIC1g05xFRVTcZnU_wCiXk1HB49_zH_dW4ZjRb985iYS5wXhcmoTK7w5fLS-I/s320/5-1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Voy a crear un nuevo proyecto que se llamara ExampleRF</div>
<span class="Apple-style-span" style="font-family: "helvetica" , "arial" , sans-serif; font-size: x-small;"><span class="Apple-style-span" style="line-height: 16px;"><br /></span></span>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPoXFQ0Wr53eXvg3zS955KHw3XWCcuNh55mJrFkzF6h6qD_c2vOAfZqefoI3ikbS5y7Jbr69Ye9uO2NSAu1Q5Pb6pabblBRLvoxocsw-4BsQrmWZnapSaBGCyv6UyfvvIUzQACy8fY2MV0/s1600/5-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPoXFQ0Wr53eXvg3zS955KHw3XWCcuNh55mJrFkzF6h6qD_c2vOAfZqefoI3ikbS5y7Jbr69Ye9uO2NSAu1Q5Pb6pabblBRLvoxocsw-4BsQrmWZnapSaBGCyv6UyfvvIUzQACy8fY2MV0/s320/5-2.png" width="259" /></a></div>
<span class="Apple-style-span" style="background-color: white; font-family: "helvetica" , "arial" , sans-serif; font-size: x-small; line-height: 16px;"><br /></span>
Como en este proyecto voy utilizar Objectify voy a descargar la librería <span class="Apple-style-span" style="background-color: white; font-family: "arial" , sans-serif; font-size: 13px;"><a href="http://code.google.com/p/objectify-appengine/downloads/detail?name=objectify-3.0.zip&can=2&q=" style="color: #0000cc; text-decoration: underline; white-space: nowrap;">objectify-3.0.zip</a> . Extraigo el zip y copio el objectify-3.0.jar en la carpeta lib del WEB-INF del proyecto y lo agrego al Build Path</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgZmVHyJtk5DV_CbBoj-JyB8rTVWyf66kJ8V8MYAJ3srkNU_wuYWSh4IgiBwJZAuP2M8dePEGhq5y72oEsJXQgjJitF9-xKp-SlHUKekuoqjhlkNkF8Us28BlwDe-pe276RzEf2NqioYtR/s1600/5-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgZmVHyJtk5DV_CbBoj-JyB8rTVWyf66kJ8V8MYAJ3srkNU_wuYWSh4IgiBwJZAuP2M8dePEGhq5y72oEsJXQgjJitF9-xKp-SlHUKekuoqjhlkNkF8Us28BlwDe-pe276RzEf2NqioYtR/s320/5-3.png" width="320" /></a></div>
<span class="Apple-style-span" style="background-color: white; font-family: "arial" , sans-serif; font-size: 13px;">Tambien debo descargar un jar adicional json-20090211.jar de este <a href="http://mvnrepository.com/artifact/org.json/json/20090211">link</a> e igualmente lo agrego al Build Path.</span><br />
<span class="Apple-style-span" style="background-color: white; font-family: "arial" , sans-serif; font-size: 13px;">Algo mas que agregue es esta libreria gwt-servlet-deps.jar al directorio lib de mi aplicación esta libreria no se agrega al BuildPath. Lo puedes encontrar en el directorio de instalación del GWT</span><br />
<span class="Apple-style-span" style="background-color: white; font-family: "arial" , sans-serif; font-size: 13px;"><br /></span>
<span class="Apple-style-span" style="background-color: white; font-family: "arial" , sans-serif; font-size: 13px;">A continuación voy a configurar el archivo de módulo para que cargue los módulos RequestFactory y Objectify.</span><br />
<span class="Apple-style-span" style="background-color: white; font-family: "arial" , sans-serif; font-size: 13px;"><br /></span>
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='examplerf'>
<inherits name='com.google.gwt.user.User'/>
<inherits name="com.googlecode.objectify.Objectify" />
<inherits name='com.google.web.bindery.requestfactory.RequestFactory' />
<entry-point class='com.examplerf.client.ExampleRF'/>
<source path='client'/>
<source path='shared'/>
</module>
</pre>
<br />
El archivo web.xml debe lucir asi:<br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>requestFactoryServlet</servlet-name>
<servlet-class>com.google.web.bindery.requestfactory.server.RequestFactoryServlet</servlet-class>
<init-param>
<param-name>symbolMapsDirectory</param-name>
<param-value>WEB-INF/classes/symbolMaps/</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>requestFactoryServlet</servlet-name>
<url-pattern>/gwtRequest</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>ExampleRF.html</welcome-file>
</welcome-file-list>
</web-app>
</pre>
<br />
Igual que en los ejemplos anteriores debo eliminar el código y archivos de ejemplo.<br />
Ahora voy a crear la estructura de directorios.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57d31o5T-Wm89O2PsReQkjobiFW7V7Vnu5Eg7tr95_XNSCan2cyX6i-qztZbNOjrlNMz4Pl-kH2IExSID8uxfeS7NJN5f7m1y8XUndZ5u6ni0fLGh_KdBbqqijz_6wLfRHJus5mE_-JFO/s1600/5-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57d31o5T-Wm89O2PsReQkjobiFW7V7Vnu5Eg7tr95_XNSCan2cyX6i-qztZbNOjrlNMz4Pl-kH2IExSID8uxfeS7NJN5f7m1y8XUndZ5u6ni0fLGh_KdBbqqijz_6wLfRHJus5mE_-JFO/s320/5-4.png" width="296" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Voy a crear una lista de colaboradores por el momento este ejemplo no tendrá interfaz gráfica y el mantenimiento lo realizare en el entry point y el listado voy a mostrarlo en consola.</div>
<div class="separator" style="clear: both; text-align: left;">
Mi clase de dominio seria Colaborador.java y lo creare en el paquete server.domain</div>
<pre class="brush:java">package com.examplerf.server.domain;
import com.googlecode.objectify.annotation.Entity;
@Entity
public class Colaborador {
private String nombres;
private String apellidos;
private Integer edad;
}
</pre>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
La clase Colaborador es una entidad Objectify. Para que pueda funcionar con RequestFactory debe tener las propiedades ID y version. De acuerdo a <a href="http://turbomanage.wordpress.com/2011/03/25/using-gwt-requestfactory-with-objectify/">David M. Chandler</a> se puede heredar de una clase DatastoreObject<span class="Apple-style-span" style="color: #2a2a2a; font-family: "verdana" , "tahoma" , "arial" , sans-serif;"><span class="Apple-style-span" style="font-size: 11px; line-height: 16px;">.</span></span><br />
<span class="Apple-style-span" style="color: #2a2a2a; font-family: "verdana" , "tahoma" , "arial" , sans-serif;"><span class="Apple-style-span" style="font-size: 11px; line-height: 16px;">
</span></span>
<pre class="brush:java">package com.examplerf.server.domain;
import javax.persistence.Id;
import javax.persistence.PrePersist;
public class DatastoreObject {
@Id
private Long id;
private Integer version = 0;
/**
* Auto-increment version # whenever persisted
*/
@PrePersist
void onPersist()
{
this.version++;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
</pre>
<span class="Apple-style-span" style="color: #2a2a2a; font-family: "verdana" , "tahoma" , "arial" , sans-serif;"><span class="Apple-style-span" style="font-size: 11px; line-height: 16px;">
</span></span>
Edito la clase colaborador para que herede de DatastoreObject
<br />
<pre class="brush:java">package com.examplerf.server.domain;
import com.googlecode.objectify.annotation.Entity;
@Entity
public class Colaborador extends DatastoreObject {
private String nombres;
private String apellidos;
private Integer edad;
public String getNombres() {
return nombres;
}
public void setNombres(String nombres) {
this.nombres = nombres;
}
public String getApellidos() {
return apellidos;
}
public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}
public Integer getEdad() {
return edad;
}
public void setEdad(Integer edad) {
this.edad = edad;
}
}
</pre>
Los getter y setter los he generado haciendo click derecho en el lugar donde se situaran del menú contextual seleccionar Source->Generate Getters and Setters...
Para la capa de persistencia el autor de <a href="http://turbomanage.wordpress.com/">turbomanage </a>utiliza una clase genérica DAO(Data Access Object) ObjectifyDao.java y una clase de excepción TooManyResultsException.java primero esta clase se sitúa en el paquete shared<br />
<pre class="brush:java">package com.examplerf.shared;
/**
* Wrapper exception that gets thrown when Objectify get() returns too many results
*/
public class TooManyResultsException extends Exception
{
/**
*
*/
private static final long serialVersionUID = -2279521172940075176L;
public TooManyResultsException()
{
super();
}
public TooManyResultsException(Throwable t)
{
super(t);
}
public TooManyResultsException(String msg)
{
super(msg);
}
public TooManyResultsException(String msg, Throwable t)
{
super(msg, t);
}
}
</pre>
<br />
<br />
Ahora copio la clase ObjectifyDao.java en el paquete server.service
<br />
<pre class="brush:java">package com.examplerf.server.service;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.Embedded;
import javax.persistence.Transient;
import com.examplerf.server.domain.Colaborador;
import com.examplerf.shared.TooManyResultsException;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;
import com.googlecode.objectify.util.DAOBase;
/**
* Generic DAO for use with Objectify
*
* @author turbomanage
*
* @param <T>
*/
public class ObjectifyDao<T> extends DAOBase
{
static final int BAD_MODIFIERS = Modifier.FINAL | Modifier.STATIC
| Modifier.TRANSIENT;
static
{
ObjectifyService.register(Colaborador.class);
}
protected Class<T> clazz;
@SuppressWarnings("unchecked")
public ObjectifyDao()
{
clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public Key<T> put(T entity)
{
return ofy().put(entity);
}
public Map<Key<T>, T> putAll(Iterable<T> entities)
{
return ofy().put(entities);
}
public void delete(T entity)
{
ofy().delete(entity);
}
public void deleteKey(Key<T> entityKey)
{
ofy().delete(entityKey);
}
public void deleteAll(Iterable<T> entities)
{
ofy().delete(entities);
}
public void deleteKeys(Iterable<Key<T>> keys)
{
ofy().delete(keys);
}
public T get(Long id) throws EntityNotFoundException
{
return ofy().get(this.clazz, id);
}
public T get(Key<T> key) throws EntityNotFoundException
{
return ofy().get(key);
}
public Map<Key<T>, T> get(Iterable<Key<T>> keys)
{
return ofy().get(keys);
}
public List<T> listAll()
{
Query<T> q = ofy().query(clazz);
return q.list();
}
/**
* Convenience method to get all objects matching a single property
*
* @param propName
* @param propValue
* @return T matching Object
* @throws TooManyResultsException
*/
public T getByProperty(String propName, Object propValue)
throws TooManyResultsException
{
Query<T> q = ofy().query(clazz);
q.filter(propName, propValue);
Iterator<T> fetch = q.limit(2).list().iterator();
if (!fetch.hasNext())
{
return null;
}
T obj = fetch.next();
if (fetch.hasNext())
{
throw new TooManyResultsException(q.toString()
+ " returned too many results");
}
return obj;
}
public List<T> listByProperty(String propName, Object propValue)
{
Query<T> q = ofy().query(clazz);
q.filter(propName, propValue);
return q.list();
}
public List<Key<T>> listKeysByProperty(String propName, Object propValue)
{
Query<T> q = ofy().query(clazz);
q.filter(propName, propValue);
return q.listKeys();
}
public T getByExample(T exampleObj) throws TooManyResultsException
{
Query<T> q = buildQueryByExample(exampleObj);
Iterator<T> fetch = q.limit(2).list().iterator();
if (!fetch.hasNext())
{
return null;
}
T obj = fetch.next();
if (fetch.hasNext())
{
throw new TooManyResultsException(q.toString()
+ " returned too many results");
}
return obj;
}
public List<T> listByExample(T exampleObj)
{
Query<T> queryByExample = buildQueryByExample(exampleObj);
return queryByExample.list();
}
public Key<T> getKey(Long id)
{
return new Key<T>(this.clazz, id);
}
public Key<T> key(T obj)
{
return ObjectifyService.factory().getKey(obj);
}
public List<T> listChildren(Object parent)
{
return ofy().query(clazz).ancestor(parent).list();
}
public List<Key<T>> listChildKeys(Object parent)
{
return ofy().query(clazz).ancestor(parent).listKeys();
}
protected Query<T> buildQueryByExample(T exampleObj)
{
Query<T> q = ofy().query(clazz);
// Add all non-null properties to query filter
for (Field field : clazz.getDeclaredFields())
{
// Ignore transient, embedded, array, and collection properties
if (field.isAnnotationPresent(Transient.class)
|| (field.isAnnotationPresent(Embedded.class))
|| (field.getType().isArray())
|| (field.getType().isArray())
|| (Collection.class.isAssignableFrom(field.getType()))
|| ((field.getModifiers() & BAD_MODIFIERS) != 0))
continue;
field.setAccessible(true);
Object value;
try
{
value = field.get(exampleObj);
} catch (IllegalArgumentException e)
{
throw new RuntimeException(e);
} catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
if (value != null)
{
q.filter(field.getName(), value);
}
}
return q;
}
/*
* Application-specific methods to retrieve items owned by a specific user
*/
}
</pre>
<br />
Se puede notar que la clase Colaborador se ha registrado en la clase ObjectifyDao. Todas las clases de entidad necesitan registrarse en esta clase.
<br />
<pre class="brush:java">static
{
ObjectifyService.register(Colaborador.class);
}
</pre>
Ahora voy a crear la clase ColaboradorDao en el paquete server.service que manejara las operaciones CRUD(Create Update Delete) del Colaborador.
<br />
<pre class="brush:java">package com.examplerf.server.service;
import com.examplerf.server.domain.Colaborador;
import com.google.appengine.api.datastore.EntityNotFoundException;
public class ColaboradorDao extends ObjectifyDao<Colaborador> {
public void save(Colaborador colaborador){
this.put(colaborador);
}
public void remove(Long id){
try {
Colaborador c = this.get(id);
this.delete(c);
} catch (EntityNotFoundException e) {
e.printStackTrace();
}
}
public Colaborador fetch(Long id){
Colaborador c = null;
try {
c = this.get(id);
} catch (EntityNotFoundException e) {
e.printStackTrace();
}
return c;
}
}
</pre>
<br />
Utilizando RequestFactory se puede exponer ColaboradorDao directamente como servicio. Para ello es necesario una clase DaoServiceLocator en el paquete server.locator.
<br />
<pre class="brush:java">package com.examplerf.server.locator;
import com.google.web.bindery.requestfactory.shared.ServiceLocator;
/**
* Generic locator service that can be referenced in the @Service annotation
* for any RequestFactory service stub
*
* @author turbomanage
*/
public class DaoServiceLocator implements ServiceLocator {
@Override
public Object getInstance(Class<?> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
</pre>
En RequestFactory se declara un proxy interface por cada entidad. En este ejemplo la interfaz será ColaboradorProxy. Pero antes RequestFactory requiere una clase Generic Entity Locator para que pueda relacionar la Entidad(la clase de dominio en el servidor) con su respectivo proxy interface(EntityProxy en el cliente). Esta clase es ObjectifyLocator y va en el paquete server.locator.
<br />
<pre class="brush:java">package com.examplerf.server.locator;
import com.examplerf.server.domain.DatastoreObject;
import com.google.web.bindery.requestfactory.shared.Locator;
import com.googlecode.objectify.util.DAOBase;
/**
* Generic @Locator for objects that extend DatastoreObject
*/
public class ObjectifyLocator extends Locator<DatastoreObject, Long> {
@Override
public DatastoreObject create(Class<? extends DatastoreObject> clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Override
public DatastoreObject find(Class<? extends DatastoreObject> clazz, Long id) {
DAOBase daoBase = new DAOBase();
return daoBase.ofy().find(clazz, id);
}
@Override
public Class<DatastoreObject> getDomainType() {
// Never called
return null;
}
@Override
public Long getId(DatastoreObject domainObject) {
return domainObject.getId();
}
@Override
public Class<Long> getIdType() {
return Long.class;
}
@Override
public Object getVersion(DatastoreObject domainObject) {
return domainObject.getVersion();
}
}
</pre>
Ahora ya puedo crear mi proxy interface ColaboradorProxy en el paquete shared.proxy.
<br />
<pre class="brush:java">package com.examplerf.shared.proxy;
import com.examplerf.server.domain.Colaborador;
import com.examplerf.server.locator.ObjectifyLocator;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
@ProxyFor(value = Colaborador.class, locator = ObjectifyLocator.class)
public interface ColaboradorProxy extends EntityProxy {
String getNombres();
void setNombres(String nombres);
String getApellidos();
void setApellidos(String apellidos);
Integer getEdad();
void setEdad(Integer edad);
}
</pre>
Ahora voy a crear el servicio ColaboradorService en el paquete shared.sevice.
<br />
<pre class="brush:java">package com.examplerf.shared.service;
import java.util.List;
import com.examplerf.server.locator.DaoServiceLocator;
import com.examplerf.server.service.ColaboradorDao;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.Service;
@Service(value = ColaboradorDao.class, locator = DaoServiceLocator.class)
public interface ColaboradorService extends RequestContext {
Request<List<ColaboradorProxy>> listAll();
Request<ColaboradorProxy> fetch(Long id);
Request<Void> save(ColaboradorProxy colaborador);
Request<Void> remove(Long id);
}
</pre>
Como puede notar en el servicio se utiliza la interfaz ColaboradorProxy no la clase de dominio Colaborador, RequestFactory se encarga de hacer el mapeo entre estos.
Ahora voy a crear la interfaz donde se definen los servicios ExampleRFRequestFactory en el paquete shared.service.
<br />
<pre class="brush:java">package com.examplerf.shared.service;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
public interface ExampleRFRequestFactory extends RequestFactory {
public ColaboradorService colaboradorService();
}
</pre>
Ahora voy a utilizar mis servicios desde el entry point utilizando SimpleEventBus para este sencillo ejemplo.
<br />
<pre class="brush:java">package com.examplerf.client;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.examplerf.shared.service.ColaboradorService;
import com.examplerf.shared.service.ExampleRFRequestFactory;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.shared.Receiver;
public class ExampleRF implements EntryPoint {
private final ExampleRFRequestFactory myRF = GWT.create(ExampleRFRequestFactory.class);
public void onModuleLoad() {
myRF.initialize(new SimpleEventBus());
guardar();
}
public void guardar(){
ColaboradorService cs = myRF.colaboradorService();
ColaboradorProxy colaborador = cs.create(ColaboradorProxy.class);
colaborador.setNombres("Juan");
colaborador.setApellidos("Perez");
colaborador.setEdad(27);
cs.save(colaborador).fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
GWT.log("Se guardo correctamente");
}
});
}
}
</pre>
Ahora ejecuto la aplicación click derecho en el proyecto Run As -> Web Application
Me muestra "Se guardo correctamente"
Los datos ingresados se pueden ver en la consola local del appengine. Ir a http://localhost:8888/_ah/admin luego click en el boton List Entities y veran la lista de entradas. Esta consola sólo esta visible si esta iniciado el servidor Jetty. Es decir si detiene la ejecución de la aplicación en Hosted Mode tampoco podrá acceder a la consola local.
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiJ_XSvKqg16szwfMWdeUFCKX848HhWW0Ws5SvmICltc4n_x9GoOcWNilcvcB0ExL6eW4Wx8bV-u3hJ8QUtqEZzX_TZnO8t0xV4APypup9BSsl_AeIVXjmb0xhxnZ1YWey-MTTV2P3S5pc/s1600/5-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="159" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiJ_XSvKqg16szwfMWdeUFCKX848HhWW0Ws5SvmICltc4n_x9GoOcWNilcvcB0ExL6eW4Wx8bV-u3hJ8QUtqEZzX_TZnO8t0xV4APypup9BSsl_AeIVXjmb0xhxnZ1YWey-MTTV2P3S5pc/s320/5-5.png" width="320" /></a></div>
<br />
Ahora agrego las funciones par editar, eliminar y listar
<br />
<pre class="brush:java">package com.examplerf.client;
import java.util.List;
import com.examplerf.shared.proxy.ColaboradorProxy;
import com.examplerf.shared.service.ColaboradorService;
import com.examplerf.shared.service.ExampleRFRequestFactory;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.web.bindery.event.shared.SimpleEventBus;
import com.google.web.bindery.requestfactory.shared.Receiver;
import com.google.web.bindery.requestfactory.shared.Request;
public class ExampleRF implements EntryPoint {
private final ExampleRFRequestFactory myRF = GWT.create(ExampleRFRequestFactory.class);
public void onModuleLoad() {
myRF.initialize(new SimpleEventBus());
//guardar();
//editar();
//eliminar();
listar();
}
public void guardar(){
ColaboradorService cs = myRF.colaboradorService();
ColaboradorProxy colaborador = cs.create(ColaboradorProxy.class);
colaborador.setNombres("marcelo");
colaborador.setApellidos("bailon");
colaborador.setEdad(30);
cs.save(colaborador).fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
GWT.log("Se guardo correctamente");
}
});
}
public void editar(){
ColaboradorService cs = myRF.colaboradorService();
Request<ColaboradorProxy> colaborador = cs.fetch(new Long(2));
colaborador.fire(new Receiver<ColaboradorProxy>() {
@Override
public void onSuccess(ColaboradorProxy response) {
GWT.log(response.getNombres());
ColaboradorService cs2 = myRF.colaboradorService();
//para poder editar
ColaboradorProxy colaborador2 = cs2.edit(response);
colaborador2.setNombres("Marcelo");
colaborador2.setApellidos("bailon");
cs2.save(colaborador2).fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
GWT.log("Se edito correctamente");
}
});
}
});
}
public void eliminar(){
myRF.colaboradorService().remove(new Long(1)).fire(new Receiver<Void>() {
@Override
public void onSuccess(Void response) {
GWT.log("Se elimino correctamente");
}
});
}
public void listar(){
myRF.colaboradorService().listAll().fire(new Receiver<List<ColaboradorProxy>>() {
@Override
public void onSuccess(List<ColaboradorProxy> response) {
for(ColaboradorProxy c : response){
GWT.log(c.getNombres() +" "+c.getApellidos());
}
}
});
}
}
</pre>
Juan Rojashttp://www.blogger.com/profile/15707282343911443051noreply@blogger.com2tag:blogger.com,1999:blog-7772385331860770062.post-45056151423699764842011-08-18T14:14:00.000-07:002016-02-12T17:49:27.899-08:00Primera aplicación usando GWTP<span class="Apple-style-span" style="font-family: "arial" , sans-serif;"><a href="http://code.google.com/p/gwt-platform/">GWTP</a> o GWT Platform es un framework que implementa el patrón MVP para simplificar el desarrollo de aplicaciones. Hace uso de <a href="http://code.google.com/p/google-gin/">GIN</a>(Client) y <a href="http://code.google.com/p/google-guice/">Guice</a>(Server) para implementar el patrón inyección de dependencia. La versión 0.6 dispone de un plugin para eclipse.</span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif;">El ejemplo a continuación muestra un ejemplo básico sin usar el Plugin de GWTP para ver un ejemplo del uso del plugin puede ver este <a href="http://www.youtube.com/watch?v=cC-Qh4q1lCI">video</a>.</span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif;"></span><br />
<a name='more'></a><span class="Apple-style-span" style="font-family: "arial" , sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif;"><b>Hello GWT</b></span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif;">Ir al Menú de eclipse File -> New -> Web Application Project</span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif; font-size: x-small;"><br />
</span><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk_aoXNV7RcyEHnCDNrQ5ukSewTM4W6Ds9cA6yEa1tCYqH4jjCkDr9V4l5PYkzWhanSBL5m9GX5tDsuT4r0EXlLI13x04ZYPhtcQS-TUUI5Kt18Nuocr-yXXHx1PmuruoMHEbfR6k1OAtC/s1600/4-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhk_aoXNV7RcyEHnCDNrQ5ukSewTM4W6Ds9cA6yEa1tCYqH4jjCkDr9V4l5PYkzWhanSBL5m9GX5tDsuT4r0EXlLI13x04ZYPhtcQS-TUUI5Kt18Nuocr-yXXHx1PmuruoMHEbfR6k1OAtC/s320/4-1.png" width="249" /></a></div>
<span class="Apple-style-span" style="font-family: "arial" , sans-serif; font-size: x-small;"><br />
</span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif;">Luego eliminar los archivos GreetingService.java , GreetingServiceAsync.java, FieldVerifier.java y eliminar el código de ejemplo del entry point.</span><br />
<br />
<pre class="brush:java">package com.hellogwtp.client;
package com.hellogwtp.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
public class HelloGWTP implements EntryPoint {
public void onModuleLoad() {
GWT.log("hello");
}
}
</pre>
<br />
El módulo<br />
<br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='hellogwtp'>
<inherits name='com.google.gwt.user.User'/>
<entry-point class='com.hellogwtp.client.HelloGWTP'/>
<source path='client'/>
<source path='shared'/>
</module>
</pre>
<br />
El archivo html<br />
<br />
<pre class="brush:html"><!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="HelloGWTP.css">
<title>Web Application Starter Project</title>
<script type="text/javascript" language="javascript" src="hellogwtp/hellogwtp.nocache.js"></script>
</head>
<body>
<!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
</body>
</html>
</pre>
<br />
También dejar en blanco el archivo css.<br />
<br />
El archivo web.xml debe tener el siguiente contenido<br />
<br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Servlets -->
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>HelloGWTP.html</welcome-file>
</welcome-file-list>
</web-app>
</pre>
<br />
Luego ejecutar el proyecto para comprobar que todo esta bien.<br />
<br />
Para poder utilizar el GWTP necesitamos descargar unas librerias.<br />
<br />
aopalliance.jar<br />
gin-1.5-post-gwt-2.2.jar<br />
guice-3.0.jar<br />
guice-assistedinject-3.0.jar<br />
gwtp-all-0.6.jar<br />
javax.inject-1.jar<br />
validation-api-1.0.0.GA-sources.jar<br />
validation-api-1.0.0.GA.jar<br />
<br />
de la página de <a href="http://code.google.com/p/google-gin/downloads/list">GIN</a> descargamos gin-1.5.zip en su contenido estan:<br />
aopalliance.jar<br />
gin-1.5-post-gwt-2.2.jar<br />
javax.inject.jar<br />
<br />
Ahora vamos a la página de <a href="http://code.google.com/p/google-guice/downloads/list">Guice</a> y descargamos guice-3.0.zip y en su contenido estan:<br />
guice-3.0.jar<br />
guice-assistedinject-3.0.jar<br />
<br />
Luego descargamos los jars validation <a href="http://repo1.maven.org/maven2/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar">validation-api-1.0.0.GA.jar</a> y <a href="http://repo1.maven.org/maven2/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA-sources.jar">validation-api-1.0.0.GA-sources.jar</a><br />
y por último vamos a la página de <a href="http://code.google.com/p/gwt-platform/downloads/list">GWTP</a> y descargamos gwtp-all-0.6.zip en su contenido esta<br />
gwtp-all-0.6.jar<br />
<br />
Todos estos 7 jars los copio al directorio war/WEB-INF/lib del proyecto y los selecciono click derecho Build Path->Add to Build Path.<br />
<br />
Luego agrego el módulo de GWTP a nuestro archivo de modulo<br />
<br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='hellogwtp'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.gwtplatform.mvp.Mvp' />
<entry-point class='com.hellogwtp.client.HelloGWTP'/>
<source path='client'/>
<source path='shared'/>
</module>
</pre>
<br />
dentro de client creo un paquete place y ahi estará la clase MyPlaceManager.java<br />
<br />
<pre class="brush:java">package com.hellogwtp.client.place;
import com.google.gwt.event.shared.EventBus;
import com.google.inject.Inject;
import com.gwtplatform.mvp.client.proxy.PlaceManagerImpl;
import com.gwtplatform.mvp.client.proxy.TokenFormatter;
public class MyPlaceManager extends PlaceManagerImpl {
@Inject
public MyPlaceManager(EventBus eventBus, TokenFormatter tokenFormatter) {
super(eventBus, tokenFormatter);
}
@Override
public void revealDefaultPlace() {
}
}
</pre>
<br />
dentro client creo el paquete gin dentro estarán la clase MyModule.java y la interfaz MyGinjector.java<br />
<br />
MyModule.java<br />
<pre class="brush:java">package com.hellogwtp.client.gin;
import com.gwtplatform.mvp.client.gin.AbstractPresenterModule;
import com.gwtplatform.mvp.client.gin.DefaultModule;
import com.hellogwtp.client.place.MyPlaceManager;
public class MyModule extends AbstractPresenterModule {
@Override
protected void configure() {
install(new DefaultModule(MyPlaceManager.class));
}
}
</pre>
<br />
MyGinjector.java<br />
<br />
<pre class="brush:java">package com.hellogwtp.client.gin;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.inject.client.GinModules;
import com.google.gwt.inject.client.Ginjector;
import com.gwtplatform.mvp.client.proxy.PlaceManager;
@GinModules({ MyModule.class })
public interface MyGinjector extends Ginjector {
PlaceManager getPlaceManager();
EventBus getEventBus();
}
</pre>
<br />
Ahora le indico a mi archivo de módulo la ubicación del Ginjector<br />
<br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='hellogwtp'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.gwtplatform.mvp.Mvp' />
<entry-point class='com.hellogwtp.client.HelloGWTP'/>
<source path='client'/>
<source path='shared'/>
<define-configuration-property name="gin.ginjector" is-multi-valued="false" />
<set-configuration-property name="gin.ginjector" value="com.hellogwtp.client.gin.MyGinjector" />
</module>
</pre>
<br />
Luego modifico el archivo entry point HelloGWTP.java<br />
<br />
<pre class="brush:java">package com.hellogwtp.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.gwtplatform.mvp.client.DelayedBindRegistry;
import com.hellogwtp.client.gin.MyGinjector;
public class HelloGWTP implements EntryPoint {
public final MyGinjector ginjector = GWT.create(MyGinjector.class);
public void onModuleLoad() {
DelayedBindRegistry.bind(ginjector);
ginjector.getPlaceManager().revealCurrentPlace();
}
}
</pre>
<br />
Hasta ahora ya se ha configurado el proyecto para usar el GWT Platform. Si ejecuta el proyecto no deben salir errores.<br />
Dentro de client creo el paquete core para los Presentadores y las Vistas.<br />
<br />
IndexPresenter.java<br />
<br />
<pre class="brush:java">package com.hellogwtp.client.core;
import com.google.gwt.event.shared.EventBus;
import com.google.inject.Inject;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.View;
import com.gwtplatform.mvp.client.annotations.NameToken;
import com.gwtplatform.mvp.client.annotations.ProxyCodeSplit;
import com.gwtplatform.mvp.client.proxy.ProxyPlace;
import com.gwtplatform.mvp.client.proxy.RevealRootContentEvent;
public class IndexPresenter extends Presenter<IndexPresenter.MyView, IndexPresenter.MyProxy> {
@ProxyCodeSplit
@NameToken("index")
public interface MyProxy extends ProxyPlace<IndexPresenter> {}
public interface MyView extends View {
}
@Inject
public IndexPresenter(EventBus eventBus, MyView view, MyProxy proxy) {
super(eventBus, view, proxy);
}
@Override
protected void revealInParent() {
RevealRootContentEvent.fire(this, this);
}
}
</pre>
<br />
Luego click derecho al paquete core New -> UiBinder y el nombre será IndexView<br />
<br />
Modifico el archivo IndexView.java<br />
<pre class="brush:java">package com.hellogwtp.client.core;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.gwtplatform.mvp.client.ViewImpl;
public class IndexView extends ViewImpl implements IndexPresenter.MyView {
private static Binder uiBinder = GWT.create(Binder.class);
interface Binder extends UiBinder<Widget, IndexView> {}
private final Widget widget;
@Inject
public IndexView() {
widget = uiBinder.createAndBindUi(this);
}
@Override
public Widget asWidget() {
return widget;
}
}
</pre>
<br />
Agrego el saludo al archivo IndexView.ui.xml<br />
<pre class="brush:xml"><!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
</ui:style>
<g:HTMLPanel>
Hello GWTP
</g:HTMLPanel>
</ui:UiBinder>
</pre>
<br />
Ahora voy a enlazar el Presenter con su vista y Proxy<br />
<br />
MyModule.java<br />
<pre class="brush:java">public class MyModule extends AbstractPresenterModule {
@Override
protected void configure() {
install(new DefaultModule(MyPlaceManager.class));
bindPresenter(IndexPresenter.class, IndexPresenter.MyView.class, IndexView.class, IndexPresenter.MyProxy.class);
}
}
</pre>
<br />
Agrego el nuevo Presenter a la interfaz MyGinjector.java<br />
<br />
<pre class="brush:java">@GinModules({ MyModule.class })
public interface MyGinjector extends Ginjector {
PlaceManager getPlaceManager();
EventBus getEventBus();
AsyncProvider<IndexPresenter> getIndexPresenter();
}
</pre>
<br />
Ahora debo indicarle a la clase MyPlaceManager.java el Place por defecto<br />
<br />
<pre class="brush:java">public class MyPlaceManager extends PlaceManagerImpl {
@Inject
public MyPlaceManager(EventBus eventBus, TokenFormatter tokenFormatter) {
super(eventBus, tokenFormatter);
}
@Override
public void revealDefaultPlace() {
revealPlace(new PlaceRequest("index"), false);
}
}
</pre>
<br />
Ejecuto el proyecto click derecho Run As -> Web Application<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />Anonymousnoreply@blogger.com5tag:blogger.com,1999:blog-7772385331860770062.post-46599400970020498792011-08-11T15:09:00.000-07:002016-02-12T17:51:00.007-08:00Activities and Places<div class="separator" style="clear: both; text-align: left;">
Activities and Places es la implementación de google del patrón MVP. Si bien es posible desarrollar páginas web estáticas utilizando Activities and Places, en la versión GWT 2.3 no hay suficiente información sobre su integración con el servidor si se puede utilizar RPC o RequestFactory. Este último requiere la clase com.google.web.bindery.event.shared.EventBus pero el ejemplo a continuación sólo funciona con com.google.gwt.event.shared.EventBus. En un desarrollo real se recomienda utilizar RequestFactory y el paquete com.google.web.bindery.event.shared ya que funciona con Aplicaciones GWT y Android.</div>
<div class="separator" style="clear: both; text-align: left;">
De acuerdo al <a href="http://www.google.com/events/io/2011/sessions/highly-productive-gwt-rapid-development-with-app-engine-objectify-requestfactory-and-gwt-platform.html">Google I/O 2011</a> recomiendan utilizar GWTP, RequestFactory y Objectify para el desarrollo de aplicaciones.</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<a name='more'></a><br />
<div class="separator" style="clear: both; text-align: left;">
El ejemplo a continuación es solo para dar una idea del funcionamiento del MVP. El código fuente lo puede descargar <a href="http://www.2shared.com/file/S_KZXmhm/PaginaWeb.html">aqui</a>.</div>
<div class="separator" style="clear: both; text-align: left;">
La estructura de la pagina web sería la siguiente:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKzzIhB2S0E8IbOwLVTKNLieiY4eaYxQicd5NzvREa0kd4f2gl9yeiturVhv04rODRCgTuMa7LpoKUVDNmOLwgWU1btR45UXabUcJIjMfApCX8_YHoJiSxE0ceKcNV8zmMooyvhhN951Ki/s1600/3-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKzzIhB2S0E8IbOwLVTKNLieiY4eaYxQicd5NzvREa0kd4f2gl9yeiturVhv04rODRCgTuMa7LpoKUVDNmOLwgWU1btR45UXabUcJIjMfApCX8_YHoJiSxE0ceKcNV8zmMooyvhhN951Ki/s1600/3-2.png" /></a></div>
<br />
Dentro del paquete client crear la interfaz ClientFactory y su implementación<br />
<br />
<pre class="brush: java">package com.paginaweb.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
public class PaginaWeb implements EntryPoint {
public void onModuleLoad() {
Window.alert("Hola Mundo");
}
}
</pre>
<br />
Su implementación<br />
<br />
<pre class="brush: java">package com.paginaweb.client;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceController;
public class ClientFactoryImpl implements ClientFactory {
private static final EventBus eventBus = new SimpleEventBus();
private static final PlaceController placeController = new PlaceController(eventBus);
@Override
public EventBus getEventBus() {
return eventBus;
}
@Override
public PlaceController getPlaceController() {
return placeController;
}
}
</pre>
<br />
Agrego unas lineas al EntryPoint<br />
<br />
<pre class="brush: java">package com.paginaweb.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.user.client.Window;
public class PaginaWeb implements EntryPoint {
public void onModuleLoad() {
ClientFactory clientFactory = GWT.create(ClientFactory.class);
EventBus eventBus = clientFactory.getEventBus();
PlaceController placeController = clientFactory.getPlaceController();
}
}
</pre>
<br />
Dentro del paquete mvp se crean 2 archivos AppActivityMapper.java y AppPlaceHistoryMapper.java<br />
<br />
<pre class="brush: java">package com.paginaweb.client.mvp;
import com.google.gwt.activity.shared.Activity;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.place.shared.Place;
import com.paginaweb.client.ClientFactory;
public class AppActivityMapper implements ActivityMapper {
private ClientFactory clientFactory;
public AppActivityMapper(ClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
@Override
public Activity getActivity(Place place) {
// TODO Auto-generated method stub
return null;
}
}
</pre>
<br />
la interfaz AppPlaceHistoryMapper <br />
<pre class="brush: java">package com.paginaweb.client.mvp;
import com.google.gwt.place.shared.PlaceHistoryMapper;
public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {
}
</pre>
<br />
Modificar el archivo del modulo PaginaWeb.gwt.xml<br />
<br />
<pre class="brush: xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='paginaweb'>
<inherits name='com.google.gwt.user.User'/>
<inherits name="com.google.gwt.place.Place"/>
<inherits name="com.google.gwt.activity.Activity"/>
<entry-point class='com.paginaweb.client.PaginaWeb'/>
<replace-with class="com.paginaweb.client.ClientFactoryImpl">
<when-type-is class="com.paginaweb.client.ClientFactory"/>
</replace-with>
<source path='client'/>
<source path='shared'/>
</module>
</pre>
<br />
En el paquete client.ui crear la interfaz IndexView.java para la vista principal<br />
<br />
<pre class="brush: java">package com.paginaweb.client.ui;
import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.ui.IsWidget;
public interface IndexView extends IsWidget {
void setName(String name);
void setPresenter(Presenter listener);
public interface Presenter {
void goTo(Place place);
}
}
</pre>
<br />
Click derecho en el paquete client.ui ir a New->UiBinder<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDp-IdH0ooTBEmWvCWlWql5VzLCzFfHVjy5O0Rl-JucYBrDKqx1ZRBJaGstQ3Sl2UK8NX-ZnbbkolfSGOUWJjD5jrMT8SDgbGYNwS8pUjCokc61pOIaydOqk5W2qfk2Qw-xLj15MuHgSG0/s1600/3-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDp-IdH0ooTBEmWvCWlWql5VzLCzFfHVjy5O0Rl-JucYBrDKqx1ZRBJaGstQ3Sl2UK8NX-ZnbbkolfSGOUWJjD5jrMT8SDgbGYNwS8pUjCokc61pOIaydOqk5W2qfk2Qw-xLj15MuHgSG0/s320/3-1.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
El asistente creara los archivos UiBinder IndexViewImpl.ui.xml y su clase manejadora IndexViewImpl.java<br />
<br />
Luego modifico la clase IndexViewImpl.java<br />
<br />
<pre class="brush: java">package com.paginaweb.client.ui;
import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
public class IndexViewImpl extends Composite implements IndexView {
private static Binder uiBinder = GWT
.create(Binder.class);
interface Binder extends UiBinder<Widget, IndexViewImpl> {
}
private Presenter listener;
private String name;
public IndexViewImpl() {
initWidget(uiBinder.createAndBindUi(this));
}
@Override
public void setPresenter(Presenter listener) {
this.listener = listener;
}
@Override
public void setName(String name) {
this.name = name;
}
}
</pre>
<br />
El archivo uibinder solo mostrara un mensaje<br />
<br />
<pre class="brush: xml"><!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
</ui:style>
<g:HTMLPanel>
Hello Activities and Places
</g:HTMLPanel>
</ui:UiBinder>
</pre>
<br />
<b>Activities and Places</b><br />
<br />
De acuerdo a la <a href="http://code.google.com/intl/es-ES/webtoolkit/doc/latest/DevGuideMvpActivitiesAndPlaces.html">página de google</a> un activity representa una acción del usuario. Un Activity no contiene Widgets ni código UiBinder. Se encarga de inicializar y cargar la correspondiente vista.<br />
Un place representa un estado particular de la interfaz.<br />
<br />
Activities son como controllers y un Place corresponde a una URL asociada a una vista.<br />
En GWT solo se utiliza un archivo HTML para un modulo, las vistas se diferencian por un #token que se añade al final de la URL.<br />
<br />
Crear la clase IndexPlace.java en el paquete client.place<br />
agregando el código necesario luce así:<br />
<br />
<pre class="brush: java">package com.paginaweb.client.place;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceTokenizer;
public class IndexPlace extends Place {
private String name;
public IndexPlace(String token){
this.name = token;
}
public String getName() {
return name;
}
public static class Tokenizer implements PlaceTokenizer<IndexPlace>{
@Override
public IndexPlace getPlace(String token) {
return new IndexPlace(token);
}
@Override
public String getToken(IndexPlace place) {
return place.getName();
}
}
}
</pre>
<br />
En la interfaz ClientFactory añado un metodo para devolver la vista IndexView<br />
<br />
<pre class="brush: java">package com.paginaweb.client;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.PlaceController;
import com.paginaweb.client.ui.IndexView;
public interface ClientFactory {
EventBus getEventBus();
PlaceController getPlaceController();
IndexView getIndexView();
}
</pre>
<br />
En la clase ClientFactoryImpl se implementa el metodo añadido:<br />
<br />
<pre class="brush: java">package com.paginaweb.client;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceController;
import com.paginaweb.client.ui.IndexView;
import com.paginaweb.client.ui.IndexViewImpl;
public class ClientFactoryImpl implements ClientFactory {
private static final EventBus eventBus = new SimpleEventBus();
private static final PlaceController placeController = new PlaceController(eventBus);
private static final IndexView indexview = new IndexViewImpl();
@Override
public EventBus getEventBus() {
return eventBus;
}
@Override
public PlaceController getPlaceController() {
return placeController;
}
@Override
public IndexView getIndexView() {
return indexview;
}
}
</pre>
<br />
Creo la clase IndexActivity.java en el paquete client.activity<br />
<br />
<pre class="brush: java">package com.paginaweb.client.activity;
import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.paginaweb.client.ClientFactory;
import com.paginaweb.client.place.IndexPlace;
import com.paginaweb.client.ui.IndexView;
public class IndexActivity extends AbstractActivity implements IndexView.Presenter {
private ClientFactory clientFactory;
private String name;
public IndexActivity(IndexPlace place, ClientFactory clientFactory){
this.name = place.getName();
this.clientFactory = clientFactory;
}
@Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
IndexView view = clientFactory.getIndexView();
view.setName(name);
view.setPresenter(this);
panel.setWidget(view.asWidget());
}
@Override
public void goTo(Place place) {
clientFactory.getPlaceController().goTo(place);
}
}
</pre>
<br />
modifico la interfaz AppPlaceHistoryMapper.java para agregarle el IndexPlace<br />
<br />
<pre class="brush: java">package com.paginaweb.client.mvp;
import com.google.gwt.place.shared.PlaceHistoryMapper;
import com.google.gwt.place.shared.WithTokenizers;
import com.paginaweb.client.place.IndexPlace;
@WithTokenizers({IndexPlace.Tokenizer.class})
public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {
}
</pre>
<br />
luego agrego el código al metodo getActivity de la clase AppActivityMapper<br />
<br />
<pre class="brush: java">package com.paginaweb.client.mvp;
import com.google.gwt.activity.shared.Activity;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.place.shared.Place;
import com.paginaweb.client.ClientFactory;
import com.paginaweb.client.activity.IndexActivity;
import com.paginaweb.client.place.IndexPlace;
public class AppActivityMapper implements ActivityMapper {
private ClientFactory clientFactory;
public AppActivityMapper(ClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
@Override
public Activity getActivity(Place place) {
if(place instanceof IndexPlace)
return new IndexActivity((IndexPlace)place, clientFactory);
return null;
}
}
</pre>
<br />
por último modifico mi clase entrypoint PaginaWeb<br />
<br />
<pre class="brush: java">package com.paginaweb.client;
import com.google.gwt.activity.shared.ActivityManager;
import com.google.gwt.activity.shared.ActivityMapper;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.paginaweb.client.mvp.AppActivityMapper;
import com.paginaweb.client.mvp.AppPlaceHistoryMapper;
import com.paginaweb.client.place.IndexPlace;
public class PaginaWeb implements EntryPoint {
private Place defaultPlace = new IndexPlace("index");
private SimplePanel appWidget = new SimplePanel();
public void onModuleLoad() {
ClientFactory clientFactory = GWT.create(ClientFactory.class);
EventBus eventBus = clientFactory.getEventBus();
PlaceController placeController = clientFactory.getPlaceController();
ActivityMapper activityMapper = new AppActivityMapper(clientFactory);
ActivityManager activityManager = new ActivityManager(activityMapper, eventBus);
activityManager.setDisplay(appWidget);
AppPlaceHistoryMapper historyMapper = GWT .create(AppPlaceHistoryMapper.class);
PlaceHistoryHandler historyHandler = new PlaceHistoryHandler(historyMapper);
historyHandler.register(placeController, eventBus, defaultPlace);
RootPanel.get().add(appWidget);
historyHandler.handleCurrentHistory();
}
}
</pre>
<br />
Ahora ejecuto click derecho en el proyecto Run As->Web Application<br />
<br />
La página muestra el mensaje<br />
<br />
Hello Activities and Places<br />
<br />Anonymousnoreply@blogger.com0tag:blogger.com,1999:blog-7772385331860770062.post-61128419520513826962011-08-10T14:59:00.000-07:002016-02-12T17:51:33.951-08:00Introducción a GWT<div class="separator" style="clear: both; text-align: left;">
</div>
<br />
GWT es un framework Open Source para el desarrollo de aplicaciones web con java cuya primera versión salió en mayo del 2006.<br />
<br />
<a name='more'></a><br /><br />
<b>Desarrollo de Software Web</b><br />
Desde la aparición de los primeros sitios web en la década de los 90 basados en texto e hipervinculos el desarrollo de software ha tenido un nuevo objetivo "Desarrollar software para la web".<br />
En la actualidad un equipo de trabajo para desarrollo de software lo conforman principalmente:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVTDSaojFln768KsZhMwdmen_EhkRuR_txtzY9v3h2hZjKhKFjA09l_bfpnMsOiOLTEP_3RzwQrnmy3B3L1xMNLSFTtmUaAnakIEIwPdiVqUsOw2vQI7gP3wwNmikvNGQVsEst1MNURUB0/s1600/2-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVTDSaojFln768KsZhMwdmen_EhkRuR_txtzY9v3h2hZjKhKFjA09l_bfpnMsOiOLTEP_3RzwQrnmy3B3L1xMNLSFTtmUaAnakIEIwPdiVqUsOw2vQI7gP3wwNmikvNGQVsEst1MNURUB0/s320/2-1.png" width="320" /></a></div>
<br />
Los programadores son los responsables en la producción del software implementa los requerimientos recogidos por el analista, convierte el diseño a HTML, cumple con el tiempo establecido del proyecto,<br />
corrige los errores encontrados por el Tester(encargado de realizar las pruebas) y realizas los cambios al sistema web.<br />
De acuerdo a esto el programador debe reunir un conjunto de habilidades: conocimientos de CSS, Javascript, HTML(Lado del Cliente), un lenguaje de servidor que puede ser PHP o Java(Lado del Servidor) y un motor de bases de datos que puede ser MySql, PostgreSQL, BigTable u otros. Los conocimientos específicos lo determina el proyecto.<br />
Con la aparición de AJAX (Asynchronous JavaScript And XML) los programadores han tenido una nueva herramienta para el desarrollo de sus aplicativos. Pero el código Javascript necesario para implementar la funcionalidad AJAX es muy tedioso. Así aparecieron librerias Javascript como JQuery, Prototype, etc. Que ofrecen sus propias funciones para lograr la funcionalidad de Ajax. Pero a medida que escribes mas código Javascript tu proyecto se vuelve ilegible por otros programadores.<br />
<br />
<span class="Apple-style-span" style="background-color: white;"><i style="font-family: arial, sans-serif; font-size: small; font-style: normal; line-height: 16px;"><br />
</i></span><br />
<span class="Apple-style-span" style="background-color: white;"><i style="font-family: arial, sans-serif; font-size: small; font-style: normal; line-height: 16px;"><b>Google Web Toolkit</b></i></span><br />
<span class="Apple-style-span" style="font-family: "arial" , sans-serif; font-size: x-small;"><span class="Apple-style-span" style="line-height: 16px;"><br />
</span></span><br />
GWT propone un modelo de desarrollo utilizando como lenguaje intermediario a Java para implementar la funcionalidad Ajax. Asi Javascript se convierte en el lenguaje ensamblador de la web.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXFcV_u2x0jT01u2AEjbjqi7n03aK7p-QDGBvjn-lJnRjlgsJz3dJ6KUQXHjatU73ZzZoqq3uUtMEjn_DgnnzJrZ_zE-d2MSblDFVafDQ7H8T-JnwlhCRauvlsp_FZReN2_CEQ3UmVwvzy/s1600/2-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXFcV_u2x0jT01u2AEjbjqi7n03aK7p-QDGBvjn-lJnRjlgsJz3dJ6KUQXHjatU73ZzZoqq3uUtMEjn_DgnnzJrZ_zE-d2MSblDFVafDQ7H8T-JnwlhCRauvlsp_FZReN2_CEQ3UmVwvzy/s320/2-2.png" width="320" /></a></div>
<br />
<br />
para lograr esto GWT tiene 3 componentes principales: El compilador Java a Javascript, el emulador JRE y el JSNI.<br />
<br />
<b>Emulador JRE</b><br />
Debido a que GWT debe compilar el Java a Javascript, necesita implementar versiones Javascript de clases Java por ejemplo java.lang.*. Se puede decir que GWT soporta solo un subconjunto de clases Java. Por ejemplo GWT no tiene una version Javascript de las clases del paquete java.sql.*.<br />
<br />
<b>JSNI(</b>Javascript Native Interface<b>)</b><br />
GWT abstrae el código javascript, pero si es necesario acceder al bajo nivel se puede implementar funciones nativas que permiten la comunicación bidireccional de tus funciones Javascript con funciones GWT.<br />
<br />
<b>Paneles y Widgets</b><br />
En GWT puedes diseñar tu interfaz con código java al estilo Swing o puedes hacer uso de UIBinder para diseñar tu interfaz con XML al estilo HTML tradicional.<br />
<br />
<b>I18N(Internacionalización)</b><br />
En GWT como en otros frameworks puedes tener archivos de idiomas según cuantos idiomas soporte tu aplicación.<br />
<br />
<b>RPC</b>(<b>Remote Procedure Call)</b><br />
El RPC es la implementación Ajax de GWT. A diferencia de las librerias Javascript que usan JSON para enviar y recibir datos del servidor. El RPC puede intercambiar objetos java, la serialización corre por parte de GWT.<br />
<br />
<b>Gestión del Historial</b><br />
En GWT es posible implementar la funcionalidad de los botones Atras y Siguiente del navegador.<br />
<br />
El flujo que sigue una aplicación web tradicional VS aplicacion GWT se puede ver a continuación<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxr4VUFb4NeNJRt6py0l6zj7iOQCO98gpkVpCzKJTYH8Co5d1WZC2hi3gjEPx44BiyjvQuL0O8E5dXavpuEfvo3z1Mgq3TpQWbCcxWt2T2NoKMo9QbLfjHqeQFvAIa3orx-umBfaHUR9Fg/s1600/2-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxr4VUFb4NeNJRt6py0l6zj7iOQCO98gpkVpCzKJTYH8Co5d1WZC2hi3gjEPx44BiyjvQuL0O8E5dXavpuEfvo3z1Mgq3TpQWbCcxWt2T2NoKMo9QbLfjHqeQFvAIa3orx-umBfaHUR9Fg/s320/2-3.png" width="320" /></a></div>
<br />Anonymousnoreply@blogger.com2tag:blogger.com,1999:blog-7772385331860770062.post-27637966447322483842011-08-10T13:02:00.000-07:002016-02-12T17:51:46.369-08:00Hola Mundo<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<b>Hola Mundo en GWT.</b></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
Para crear un proyecto en GWT voy a utilizar el plugin de Google para Eclipse.</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
Voy a File->New->Web Application Project</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br />
<a name='more'></a><br /></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
El proyecto se llamara PaginaWeb y se llenan los datos como la imagen a continuación.En este proyecto no se utilizara el App Engine y voy a generar un proyecto con código de ejemplo.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvkATgbdkSD8UyGyAGoLI5-lCm0GwKVMp3EjTTE_plN8oMcOP-A9Iza4_2WuV40m5MGahpinofn-kxt6m2YM9rSh0ZE0kZ-7ZnusAZBpftBsl3Ru60CG0TSMyPRx838kNztHnglR-H30eE/s1600/1-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvkATgbdkSD8UyGyAGoLI5-lCm0GwKVMp3EjTTE_plN8oMcOP-A9Iza4_2WuV40m5MGahpinofn-kxt6m2YM9rSh0ZE0kZ-7ZnusAZBpftBsl3Ru60CG0TSMyPRx838kNztHnglR-H30eE/s320/1-4.png" width="250" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
A continuación voy a eliminar los archivos de ejemplo: FieldVerifier.java, GreetingServiceImpl.java, GreetingServiceAsync.java, GreetingService.java</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Luego limpio el archivo de entry point <b>PaginaWeb.java</b>.</div>
</div>
<pre class="brush: java">package com.paginaweb.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
public class PaginaWeb implements EntryPoint {
public void onModuleLoad() {
Window.alert("Hola Mundo");
}
}
</pre>
<br />
<br />
También Limpio el modulo <b>PaginaWeb.gwt.xml</b><br />
<br />
<pre class="brush: xml"><?xml version="1.0" encoding="UTF-8"?>
<module rename-to='paginaweb'>
<inherits name='com.google.gwt.user.User'/>
<entry-point class='com.paginaweb.client.PaginaWeb'/>
<source path='client'/>
<source path='shared'/>
</module>
</pre>
<br />
<br />
El HTML quedaría así <b>PaginaWeb.html</b>:<br />
<br />
<pre class="brush: html"><!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="PaginaWeb.css">
<title>PaginaWeb</title>
<script type="text/javascript" language="javascript" src="paginaweb/paginaweb.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
</body>
</html>
</pre>
<br />
El archivo <b>PaginaWeb.css</b> lo dejo en blanco.<br />
<br />
El archivo war/WEB-INF/web.xml limpio se muestra asi:<br />
<pre class="brush:xml"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<welcome-file-list>
<welcome-file>PaginaWeb.html</welcome-file>
</welcome-file-list>
</web-app>
</pre>
<br />
Hago click derecho en el proyecto Run As->Web Application<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXFVLa3cB7L0ojBmUZbufahdL8T-c67qiA0v3m7JW9hyphenhyphenbpmFdv1cv5V12jV69rIV0mPnujzN7BOiswot_jbho_mk_qg0t2bXxJpiiMQ0Nl8KXmmdzbVA0b25XGf09RT-lPbH-joVqcAHwT/s1600/1-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXFVLa3cB7L0ojBmUZbufahdL8T-c67qiA0v3m7JW9hyphenhyphenbpmFdv1cv5V12jV69rIV0mPnujzN7BOiswot_jbho_mk_qg0t2bXxJpiiMQ0Nl8KXmmdzbVA0b25XGf09RT-lPbH-joVqcAHwT/s320/1-5.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Puedo copiar la url o hago click derecho o doble click para abrir el navegador. Se recomienda usar los navegadores Firefox o Chrome o ambos.<br />
A continuación instalo el plugin para Chrome para ejecutar el proyecto en Hosted Mode<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1yPaETbrvOtDDNH-vAADhGCcuY_cosOGWLGoANK6_27l1KB9AJ_kPHtBwH4SPyUoywY0li43WSNxcClUBLXAkMuPVin86QlR2SSdO0z1_y_m0y5U0XcgVLC2Vu9tnw9G5lfsC26Ss_SAJ/s1600/1-6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="124" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1yPaETbrvOtDDNH-vAADhGCcuY_cosOGWLGoANK6_27l1KB9AJ_kPHtBwH4SPyUoywY0li43WSNxcClUBLXAkMuPVin86QlR2SSdO0z1_y_m0y5U0XcgVLC2Vu9tnw9G5lfsC26Ss_SAJ/s320/1-6.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
Luego de instalar actualizo la página<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixnbMNJrZ7eMkDuVF7WE7X5Tz4UFEI3dSKj-Q5medbp-U9ory5O9IOmMJTfFCvhSbg42z50G-yET6iVYo6JajRqhLymGahJdFy8Tq3lMmzXZtmhZItpVaIvXAPZMY7HStsZFqjv0DMIGY7/s1600/1-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="109" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixnbMNJrZ7eMkDuVF7WE7X5Tz4UFEI3dSKj-Q5medbp-U9ory5O9IOmMJTfFCvhSbg42z50G-yET6iVYo6JajRqhLymGahJdFy8Tq3lMmzXZtmhZItpVaIvXAPZMY7HStsZFqjv0DMIGY7/s320/1-7.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />Anonymousnoreply@blogger.com1tag:blogger.com,1999:blog-7772385331860770062.post-87120839663491777892011-08-02T15:15:00.000-07:002016-02-12T17:52:02.600-08:00Instalar Eclipse y GWT<b>Technology Stack</b><br />
JDK 6<br />
GWT 2.3<br />
<br />
<b>IDE & Plugins</b><br />
<b><br />
</b><br />
<span class="Apple-style-span" style="color: #111111; font-family: "arial" , sans-serif; font-size: 16px; line-height: 16px;">Eclipse IDE for Java Developers(Indigo 3.7)</span><br />
<span class="Apple-style-span" style="color: #111111; font-family: "arial" , sans-serif; font-size: 16px; line-height: 16px;"><a href="http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a></span><br />
<br />
Plugins<br />
<br />
Google Eclipse<br />
<a href="http://code.google.com/intl/es-ES/webtoolkit/download.html">http://code.google.com/intl/es-ES/webtoolkit/download.html</a><br />
<br />
<a name='more'></a><br /><br />
<b>Instalar GWT(Google Web Toolkit)</b><br />
Luego de descargar gwt-2.3.0.zip de <a href="http://code.google.com/intl/es-ES/webtoolkit/download.html">http://code.google.com/intl/es-ES/webtoolkit/download.html</a><br />
solo hay que descomprimir el zip para instalarlo.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<b>Instalar Eclipse</b><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
Una vez descargado eclipse-java-indigo-win32.zip voy a extraer en D:\<br />
ejecutamos eclipse.exe de D:\eclipse (Instalación en windows),<br />
he creado en el disco D una carpeta "codigofuente" que será el workspace de eclipse.<br />
<br />
Por defecto eclipse usa el JRE(Java Runtime Environment) pero es recomendable configurarlo para que utilice JDK (Java Development Kit).<br />
<br />
<b>Configurar Eclipse para que use el JDK</b><br />
Una vez abierto Eclipse vamos a Windows->Preferences->Java->Installed JREs y agregamos la ubicacion del JDK.<br />
Hacemos click en el botón Add...<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn9lHBbz8UCoRmZBo-aQSJb0_Jce8mnUByHxjp1G-wqC7M0NeZGtN6-D_eR4bG0X6MmDqV9zmWUE7vifxJb-0JfwiNBiIQ0_ODce-UWBv2knpzJ2bI2k9Hbt6sQNXxixsBagkXfDmWi4S6/s1600/1-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn9lHBbz8UCoRmZBo-aQSJb0_Jce8mnUByHxjp1G-wqC7M0NeZGtN6-D_eR4bG0X6MmDqV9zmWUE7vifxJb-0JfwiNBiIQ0_ODce-UWBv2knpzJ2bI2k9Hbt6sQNXxixsBagkXfDmWi4S6/s320/1-1.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
A la ventana Add JRE le damos Next y nos aparacera la siguiente pantalla<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0NWhpt0va-xZleKxxZv1gXx9Okm1TmkJjy2wqg4kXz_WY3vBdh-IZQsz5oTu2nm7ouAC9YAqmK29Apr5hc1uSQ-TV0QLw-YTFMR9ZfBHX_7O_7zJXj5ZvEHJJOSesimFPbC-mQJx-JI-k/s1600/1-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0NWhpt0va-xZleKxxZv1gXx9Okm1TmkJjy2wqg4kXz_WY3vBdh-IZQsz5oTu2nm7ouAC9YAqmK29Apr5hc1uSQ-TV0QLw-YTFMR9ZfBHX_7O_7zJXj5ZvEHJJOSesimFPbC-mQJx-JI-k/s320/1-2.png" width="310" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
Aquí buscamos el directorio de instalación del JDK haciendo click en el botón Directory... luego le damos al botón Finish.</div>
<div class="separator" style="clear: both; text-align: left;">
<b><br />
</b></div>
<div class="separator" style="clear: both; text-align: left;">
<b>Instalar el Plugin GWT para Eclipse</b></div>
<div class="separator" style="clear: both; text-align: left;">
La instalación del "Plugin for Eclipse" lo voy hacer online desde Eclipse IDE(Integrated Development Environment). En <a href="http://code.google.com/intl/es-ES/webtoolkit/download.html">http://code.google.com/intl/es-ES/webtoolkit/download.html</a> esta la url de actualización</div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: 13px; line-height: 16px;">http://dl.google.com/eclipse/plugin/3.7 </span><span class="Apple-style-span" style="font-family: monospace; font-size: 13px; line-height: 16px;">que se utilizará para la instalación online del plugin. Vamos al menú Help->Install New Software...->Add..</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span class="Apple-style-span" style="color: #007000; font-family: monospace; font-size: x-small;"><span class="Apple-style-span" style="line-height: 16px;"><br />
</span></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
Llenamos los datos como en la siguiente imagen y le damos Ok<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYETllBzp5jboBHuUSZcQbeTfYtqO76xIgbFo50GxEs5NQ09mQbSpun7CeaLGCtLvJel6rjn1RnV52LeT7ecFghXjg0efffArgR6K-bPn7N5UJXFBqF3F5x-Wzc1y2o_Aoi0HxHX8ohqhd/s1600/1-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="123" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYETllBzp5jboBHuUSZcQbeTfYtqO76xIgbFo50GxEs5NQ09mQbSpun7CeaLGCtLvJel6rjn1RnV52LeT7ecFghXjg0efffArgR6K-bPn7N5UJXFBqF3F5x-Wzc1y2o_Aoi0HxHX8ohqhd/s320/1-3.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
Luego Eclipse muestra las opciones a instalar. No seleccionar el GWT SDK(Software Development Kit) porque ya esta instalado. Solo seleccionar el plugin.<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
Le damos Next > Next> Aceptamos la licencia y le damos Finish. Luego esperamos a que el Eclipse termine de instalar el plugin. cuando Aparece un mensaje Security Warning le damos Ok. Luego aparece un mensaje para reiniciar el IDE le damos Restart Now.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Ya esta listo nuestro entorno de desarrollo.</div>
<b><br />
</b>Anonymousnoreply@blogger.com0