Interface ServerDataIntegration


public interface ServerDataIntegration

Server DataSource Integration

Server Data Integration means:
  • You install the Smart GWT Java Server Framework into any J2SE/J2EE environment, including any existing web application
  • You create DataSources via an XML declaration, possibly on-the-fly from existing metadata.
  • Server communication for components bound to these DataSources is handled automatically with a highly efficient, compressed protocol. You work with clean Java APIs instead of dealing with the details of XML or JSON over HTTP.
  • You can use built-in connectors for SQL, Hibernate and other common data providers without writing any code, or you can easily build your own connectors in Java.
  • Whether using the built-in connectors or custom connectors, declarations in your DataSource control a large set of server features that can make common types of business logic entirely declarative
This approach is in contrast to Client-side Data Integration in which client-side DataSources are configured to send and receive HTTP messages containing XML, JSON or other content.

Server-side Request Processing

Client-side DataBoundComponents will send DSRequests to the Smart GWT Server as background communications transparent to the user. Integrating Smart GWT's DataSource layer with your data model is a matter of handling these DSRequests and sending back DSResponses, in order to fulfill the 4 basic operations of the DataSource Protocol.

Out of the box, Smart GWT is set up to route all DSRequests through a special servlet called IDACall.

Note that the Smart GWT SDK includes detailed Javadoc reference for this servlet and all shipped Smart GWT Java server classes.

Requests that go through IDACall have the following lifecycle:

  • The overall HTTP request is received by the IDACall servlet. Smart GWT supports queuing of transactions, so each HTTP request might contain multiple DSRequests.
  • IDACall sets up an instance of RPCManager to manage the processing of the entire queue of transactions. For every DSRequest in the queue, this RPCManager:
    • Validates the DSRequest
    • Checks the DataSource configuration for customizations implemented via server scripting or DMI - in other words, your code - and passes the request to this logic.

      As described later in this section, your code can perform some custom logic here: either completely fulfilling the request, or alternatively modifying the request and causing the default processing of the request to continue

    • Calls the DataSource's execute method to obtain a DSResponse.
  • Having processed all requests, the RPCManager now serializes all the DSResponses and sends them back to the browser as a single HTTP response

This basic request handling flow can be customized at a number of points:

  • If you need an overarching authentication service, this is best implemented using servlet Filters to intercept unauthenticated requests before they reach the IDACall servlet
  • The DataSource.serverType specification within your .ds.xml configuration file is used to specify a standard server-side connector to service your requests.
  • General custom business logic can be added in a number of ways, both declaratively and programmatically:
    • The <criteria> and <values> properties of an OperationBinding allow you to modify the dataSource request dynamically at transaction-processing time, using built-in Velocity support.
      Note this feature also allows developers to use Transaction Chaining to dynamically set data values according to the results of earlier transactions.
    • For editing, standard DataSourceField.validators defined in the .ds.xml file will be processed on both the client and the server. In addition to the built-in validator types, entirely custom server validation logic may be implemented using "serverCustom" type validators.
    • For SQL DataSources, use SQL Templating to change, add to or even completely replace the SQL sent to the database, including calling stored procedures
    • The DataSource.serverConstructor allows you to specify an explicit custom DataSource subclass to create as your DataSource instance. This must be a subclass of BasicDataSource.
      When requests are recieved by the IDACall servlet, they will be passed to standard methods on this DataSource, which can be overridden for custom behavior.
      Validation is performed via a call to the validate() method.
      The request is processed by the execute(), method which can be overridden directly, or developers may override the operation-specific methods executeFetch(), executeAdd(), executeUpdate, or executeRemove() called from the standard execute() implementation.
      This approach allows you to either extend one of the built-in persistence mechanisms by subclassing a shipped class such as SQLDataSource, or create an entirely custom implementation from scratch.
      A custom dataSource will still take full advantage of DataSource-agnostic features of the Smart GWT Server, like validation, queuing, transaction chaining, support for Velocity templating, and so on.
      For more information see the custom server dataSource overview
    • Use Direct Method Invocation to call directly into your own Java classes. An operation configured to use DMI will invoke the specified method instead of running through the standard DataSource execute() method directly - the DMI implementation can then use dsRequest.execute() to call the default behavior. This means DMIs allow you to modify the DSRequest before it executes, modify the DSResponse before it returns, or replace the default behavior with unrelated actions. Note that DMI can be applied to all operations, or to individual operation bindings, and can be used in conjunction with a custom dataSource.
    • Use server scripting to add small amounts of business logic right in your .ds.xml file (either per operation, or as standard handling for all operations). DMI scripts allow you to add business logic just like normal DMIs, but don't require the logic to be in a separate .java file.

  • If you need to use a Front Controller servlet for some other reason than authentication - for example, you are using Spring some other similar system which requires that all requests go through some particular servlet - just call RPCManager.processRequest() within your Spring Controller or whatever the equivalent is in the framework in use.

    However, note carefully that taking this approach is often a sign that the Smart GWT architecture has not been correctly understood. Smart GWT is architected for client-server data communication, as opposed to early web MVC frameworks which do everything on the server. In particular, it is absolutely incorrect to represent every individual DataSource operation - or even every DataSource - as a separate Spring Controller because this implies different URLs for different operations. All DataSource operations should go through a single URL in order to allow transaction queuing - see these @see Queuing examples.

For more information on the DMI subsystem, see the DMI overview, DMI class and the DMI example in the Feature Explorer.

Note that, as you continue to integrate your prototype with your backend, you can use a mixture of DataSources that have been fully integrated with your backend and DataSources that are running in "client-only" mode (see ClientOnlyDataSources).

Important methods for handling DataSource requests

The basic flow of logic for handling DataSource requests is:

1. Determine operation type (Fetch, Add, Update, Remove) for a single request. Not necessary if you follow the recommendations for writing a custom DataSource and provide your implementation via executeFetch(), executeAdd(), et al. dsRequest.getOperationType()
2. Get inbound values (Add, Update) and/or criteria (Fetch, Update, Remove) for this request. dsRequest.getFieldValue()
dsRequest.getValues()
dsRequest.getCriteria()
3. Business logic, validation, calls to data and service tiers... anything you can code. execute custom logic
4. Set status and data for the response. dsResponse.setStatus()
dsResponse.setData()

For more information, see the RPCManager documentation, and the Custom ORM DataSource example.

See Also: