Showing posts with label gwt. Show all posts
Showing posts with label gwt. Show all posts

Sunday, February 13, 2011

Emulate a non supported class in GWT

To develop with GWT, only a Java SDK subset is available, plus GWT specific classes. Mainly (look at JRE emulation for details):

  • java.lang
  • java.lang.annotation
  • java.util
  • java.io
  • java.sql

This emulation mechanism is used to bypass GWT limitations, such as, no reflection due to the JavaScript translation.

As GWT support only a few JDK classes, as developers, we often miss something to do the work. To fill the gap, it is easy to use emulation to implement a full GWT compliant class. To do so, the best practice is to create a directory out of the class path named super, that will contain the emulations. The name of this directory has no importance, it is just done that way in GWT sources. Your package structure takes place under this directory. At this place, a module must be created, it contains only a super-source directive as following:

<super-source path="source_location"/>

path attribute provides the root directory of simulated classes. For example, to simulate a class from package java.io:

The reason to not include emulated classes in classpath, is, these classes must declare the package name from the class they emulate, not the package previously defined:

package java.io;

Now, to use these classes, you should only inherits from the emulation module.

Monday, November 15, 2010

GWT 2.1: Request Factory

RequestFactory is the new machanism to ease client/server data transfer. It brings you the possibility to define data centric code on server side, and to define business component on client side.

Entity

It is the base class of the mechanism. It is the DAO implementation class and it should be located to a shared package (accessible from both, client side and server side). It is not mandatory that this entity be a JPA entity, but RequestFactory constraints made entities looks like JPA entities.

public class Employee {
private String userName;
private String department;
private String password;
private Long id;
private Employee supervisor;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Employee getSupervisor() {
return supervisor;
}
public void setSupervisor(Employee supervisor) {
this.supervisor = supervisor;
}

public static Long countEmployees() {
return 2l;
}

public void persist() { }

public static Employee findEntity(Long id) {
return new Employee();
}

public Integer getVersion() {
return 0;
}
}
Above, we can see a POJO that defines en Employee. It implements getter end setters for each attribute, and methods countEmployees, findEntity and getVersion. Methods findEntity and getVersion are mandatory and are used internally by RequestFactory. Method countEmployees

is a data access method that could be used on client.

Entity Proxy

Entity proxy is the entity client side representation, well known as Data Transfer Object. It must implements EntityProxy and provides methods to access (read/write) to data stored in the entity. You haven't to provides data access methods such as countEmployees().

@ProxyFor(Employee.class)
public interface EmployeeProxy extends EntityProxy {

String getUserName();
void setUserName(String userName);
String getDepartment();
void setDepartment(String department);
String getPassword();
void setPassword(String password);
Long getId();
void setId(Long id);
Employee getSupervisor();
void setSupervisor(Employee supervisor);
}
Annotation @ProxyFor specifies the entity class to proxy. EntityProxy are objects used on client side, as Entities are objects user on server.

Request

Request defines an interface to use data access method. It is interface that deals with the server, and it can be seen as the service interface.
@Service(Employee.class)
public interface EmployeeRequest extends RequestContext {

Request<Long> countEmployees();

InstanceRequest<EmployeeProxy, Void> persist();
}

This interface defines methods that can be served and must be the same signature (except for return type) than the concrete service (on server). The return type must be a Request object parameterized with the return type of the server service. Request class is used for static methods, for instance method, such persist, it is InstanceRequest that is used to specify the instance type, and the method return code.

Annotation @Service gives the service class object. In our case, it is the same than the entity, but it can be different. It is only a current practice in JPA to merge DAO and entity.

Request Factory

RequestFactory allows to define a central point to create each RequestContext implementation. It is the interface that is directly instanciated (via deferred binding) by the developer.

public interface EmployeeRequestFactory extends RequestFactory {

EmployeeRequest employeeRequest();
}

Putting it all together

To use al of this stuff, first, we have to declare RequestFactory servlet:
<servlet>
<servlet-name>gwtRequest</servlet-name>
<servlet-class>com.google.gwt.requestfactory.server.RequestFactoryServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>gwtRequest
<url-pattern>/gwtRequest
</servlet-mapping>

And we have to create the RequestFactory and to give it a EventBus:
EmployeeRequestFactory factory = GWT.create(EmployeeRequestFactory.class);
factory.initialize(new SimpleEventBus());

Now, we can use it. To call a server side static method, we have to get the RequestContext and call the method on it. To execute it effectively, Request defines a method fire that executes the method to the server, and takes a Receiver in parameter. Receiver provides callback methods to execute some code. Defined callback are:

  • onFailure: in case of an error occured on server
  • onSuccess: to get the result
  • onViolation: when validation failed. Validation is supported by the RequestFactory. Validation rules should be set on entity.
factory.employeeRequest().countEmployees().fire(new Receiver<Long>() {
@Override
public void onSuccess(Long response) {
// implementation
}
});

Creating a proxy should not be done by using deferred binding (GWT.create):

EmployeeProxy employee = factory.employeeRequest().create(EmployeeProxy.class);

One time a proxy is created, we can persist it on server:

factory.employeeRequest().persist().using(employee).fire();

A call to fire() is equivalent to:

fire(new Receiver() {
@Override
public void onSuccess(Object response) {
// implementation
}
});

RequestFactory supports relationship, it sends a whole object rgaph for persistence, but it does not support embedded object.

Wednesday, October 13, 2010

GWT 2.1 RC 1 out

Finally, GWT 2.1 RC 1 is available for download at this address: here. The new features are:

  • an editor API to bind bean to widget
  • cell widgets to manage widgets based on huge data amount
  • validation API based on JSR 303
  • logging API as a simulation of JDK logging API
  • MVP framework
  • request factory, an API to bind JPA entities to GWT bean
  • SafeHTML, a more secure way to inject HTML into DOM hierarchy

Part of these features were originally part of the GWT 2.2 roadmap.

Documentation is already release for several API such as Activities/Places (MVP),RequestFactory, logging API, SafeHTML and Cell-based widgetAPI.

Sunday, July 25, 2010

GWT 2.1: logging API

One of the new functionality implemented into GWT 2.1 M2 is a Java logging API. The development team doesn't choose to implements a new API, but to use the logging API provided by Java SDK by emulating it. So, to use it, you just should create a logger as usual in your class and use it like that:


public class Gwt_log implements EntryPoint {
// create the logger
private static final Logger logger = Logger.getLogger(Gwt_log.class.getName());

public void onModuleLoad() {
// use it
logger.info("Module is loading");
}
}


As usual in GWT, your module, to use this API, must inherit from the logging module:

<inherits name='com.google.gwt.logging.Logging'/>

Inherit from this module set a numerous properties dedicated to logging API:
  • gwt.logging.enabled: enable or disable logging API, set to TRUE by default,
  • gwt.logging.logLevel: logging level, by default, set to INFO. Other available values are: ALL, FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE,
  • gwt.logging.consoleHandler: log message into the IDE console, by default, set to ENABLED. It doesn't have any effect in production mode,
  • gwt.logging.developmentModeHandler: log message into dev mode console. By default, set to ENABLED,
  • gwt.logging.firebugHandler: log message into Fiebug console. By default, set to ENABLED,
  • gwt.logging.popupHandler: log message into a popup window into the GWT application. By default, set to ENABLED,
  • gwt.logging.systemHandler: log message with a level upper than WARNING on System.err, else, on System.out. By default, set to ENABLED,
  • gwt.logging.simpleRemoteHandler: log message on server side by using a service defined by GWT. By default, set to ENABLED.
To use the remote logging capabilities of GWT, an additional effort is needed. GWT provides a service that logs message on server side. It implements a simple delegate log, by using the standard Java logging API, of the messages logged on client side. So, the logging on server side can be configured in any manner you usually do. You only need to declare the service into the file web.xml as following:
<servlet>
<servlet-name>remoteLogger</servlet-name>
<servlet-class>com.google.gwt.logging.server.RemoteLoggingServiceImpl</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>remoteLogger</servlet-name>
<url-pattern>/gwt_log/remote_logging</url-pattern>
</servlet-mapping>

In future post, I will explain how to use the MVP framework, the validation API, the new paging table widgets, and the new binding mechanism between client and server.

For other feature, have a look to: GWT 2.1: validation API.

Friday, July 16, 2010

New GWT versions

GWT 2.0.4 is available

Apple has recently released Safari 5, which include a bug where non-integral right-shifts were not being evaluated properly.
In case you experienced this bug, you need to recompile and redeploy your application.
The release is available here.

GWT 2.1 Milestone 2

This new version brings some improvement of the previous milestone:
  • simplification the process of configuring a RequestFactory
  • made record creation within a RequestFactory more extensible
  • moved project out of bikeshed
A full list of new festure and bug fixed can be found here.
The milestone is available here.