четверг, 21 июля 2011 г.

What is Crux?

http://code.google.com/p/crux-framework/

Crux is a component framework created over GWT for fast development of web applications. It is derived from a masters degree dissertation defended in 2008 at the Federal University of Minas Gerais (UFMG) - Minas Gerais, Brazil - which can be read here (only available in Portuguese).

Crux is now maintained by as an open source project.

The following documentation assumes that you are familiar with GWT. If this is not the case, please consult its documentation first.

What can Crux do?

Crux allows you to create web user interfaces in a declarative and modularized way, which drastically improves development speed and code maintainability. In other words, it brings you the best of both worlds: the comfort of creating pages with HTML and the elegance of controlling those pages using Java code.

For an overview of it's features, take a look at the Crux showcase:

Some features provided by Crux are:

  • An innovative template mechanism, which enables the reuse of HTML pages;
  • A set of powerful client widgets, like data grids, wizards and tabbed pages;
  • Support for cross-module and cross-Document communication;
  • Automatic binding of values between page widgets and controller's value objects;
  • Declarative event handling;
  • Declarative internationalization;
  • Validation engine, based on Java annotations;
  • Front Controller approach on server side;
  • Support for data sources to widgets;
  • Easy integration with other back end frameworks, like spring, guice or anything else.
  • A better MVC approach, where the controllers reside on the client side of the application;

When we talk about controllers residing on the client, we are talking about faster applications. Unlike most existing Web MVC frameworks, GWT-based solutions can manipulate the user interface where it is cheapest to be done: directly and entirely within the browser, without accessing the server. This means you only call the server to send and receive business data.

As mentioned earlier, Crux has a set of rich client widgets. But there's more: all GWT widgets are available for using with Crux, declaratively. Furthermore, it is easy to create new widgets or even plug in an already existent set of them. For more information about custom widgets, take a look at the Widget Developer Manual.

Simple Example

The following example illustrates how to create a simple HTML page with Crux and how to interact with it using a Java controller.

The page:

<html 
   
xmlns="http://www.w3.org/1999/xhtml"
   
xmlns:crux="http://www.cruxframework.org/crux"
   
xmlns:gwt="http://www.cruxframework.org/crux/gwt">
   
<head>
     
<title>My Page</title>
   
</head>
   
<body>
     
<script type="text/javascript" src="cruxexample.nocache.js"></script>
     
<crux:screen useController="myController"/>
     
<table>
         
<tr>
           
<td>
               
<gwt:textBox id="nameTextBox"/>
           
</td>
           
<td>
               
<gwt:button id="helloButton" onClick="myController.sayHello" text="Say Hello!" />
           
</td>
         
</tr>
         
<tr>
           
<td colspan="2">
               
<gwt:label id="greetingLabel"/>                  
           
</td>      
         
</tr>
     
</table>
   
</body>
</html>

The controller:

package crux.examples.client.controller;

import org.cruxframework.crux.core.client.screen.Screen;
import org.cruxframework.crux.core.client.controller.Controller;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;

@Controller("myController")
public class MyController {

       
@Expose
       
public void sayHello() {

               
TextBox textBox = Screen.get("nameTextBox", TextBox.class);
               
String name = textBox.getValue();
               
               
Label label = Screen.get("greetingLabel", Label.class);
                label
.setText("Hello, " + name + "!");
       
}      
}

The result:

Using the annotation @Controller, the class MyController is exposed to the page, under the alias myController. Then, it is ready to be used as an event handler for the button helloButton or for any other widget in the page. The helloButton contains a click event pointing to myController.sayHello. This means that a method called sayHello, exposed by the annotation @Expose, will be invoked on the controller myController to handle click events from helloButton.

Example with server interaction

This example illustrates how you can interact with server using Crux. Consider the same HTML page from the previous example. The controller class was modified to access the remote server and now looks like this:

package crux.examples.client.controller;

import org.cruxframework.crux.core.client.screen.Screen;
import org.cruxframework.crux.core.client.controller.Controller;
import org.cruxframework.crux.core.client.controller.Create;
import org.cruxframework.crux.core.client.rpc.AsyncCallbackAdapter;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import crux.examples.client.remote.GreetingServiceAsync;

@Controller(value="myController")
public class MyController {
       
       
@Create
       
protected GreetingServiceAsync service;
       
       
@Expose
       
public void sayHello() {
               
               
TextBox textBox = Screen.get("nameTextBox", TextBox.class);
               
final String name = textBox.getValue();
               
                service
.getHelloMessage(name, new AsyncCallbackAdapter<String>(this){

                               
@Override
                               
public void onComplete(String result){
                                       
Label label = Screen.get("greetingLabel", Label.class);
                                        label
.setText(result);          
                               
}
                       
}
               
);
       
}
}

The GreetingServiceAsync interface, which resides on client side, is given below:

  package crux.examples.client.remote;

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

public interface GreetingServiceAsync
{
       
public void getHelloMessage(String name, AsyncCallback<String> callback);
}

It has a sibling synchronous interface, shared by server and client sides:

package crux.examples.client.remote;

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

public interface GreetingService extends RemoteService
{
       
public String getHelloMessage(String name);
}

And, finally, the server-side business class (implementing the last given interface):

package crux.examples.server;

import crux.examples.client.remote.GreetingService;

public class GreetingServiceImpl implements GreetingService
{
       
public String getHelloMessage(String name)
       
{
               
return "Server says: Hello, " + name + "!'";
       
}
}

As you can observe, it is pretty similar to pure GWT way to communicate. In fact you can also use that way if you want. The main differences in Crux's approach are:

  1. You don't need to add a servlet declaration in the GWT module neither in the web.xml file for each new service you create.
  2. Your service implementation class does not need to extend the GWT RemoteServiceServlet. It just needs to implement the service interface.
  3. You don't need to inform through ServiceDefTarget.setServiceEntryPoint the path for your service neither use the RemoteServiceRelativePath annotation on your service interface. Crux provides a front controller for handling that.
  4. You can use the annotation @Create rather than GWT.create method. It can be used not only for services, but for any field in your controllers.

Do you want learn more about Crux? Take a look at the User Manual.

Комментариев нет:

Отправить комментарий