Interface SpringIntegration


public interface SpringIntegration

Integration with Spring

Overview

The Spring framework has many different parts, from integration with Object Relational Mapping (ORM) and transaction management systems, to a Model View Controller (MVC) architecture.

If you are building a new application from scratch and/or you are trying to modernize the presentation layer of an existing application, most of Spring MVC is inapplicable in the Smart GWT architecture. Specifically, Smart GWT renders all HTML on the client, and the server is responsible only for retrieving data and enforcing business rules. This means that Spring's ModelAndView and all functionality related to retrieving and rendering Views is unnecessary in Smart GWT. Smart GWT only needs the Model, and provides methods to deliver that Model to Smart GWT components (the server side method DSResponse.setData()).

However, Spring's DispatchServlet, Handler chain, and Controller architecture is applicable to Smart GWT. See "Using Spring Controllers" below.

Existing Spring Application

As discussed under the general server integration topic, integrating Smart GWT into your application involves finding a way to provide data that fulfills the DataSource requests sent by Smart GWT components.

There are 2 approaches for integrating Smart GWT into an existing Spring application:

  • call Spring beans via Smart GWT DMI or custom DataSources [Recommended]: use Smart GWT Direct Method Invocation (DMI) to map DataSource requests to beans managed by Spring, via ServerObject.lookupStyle:"spring". Return data to the browser by either simply returning it from your method, or via creating a DSResponse and calling DSResponse.setData() (server-side method). Or, use a similar approach based on custom DataSource implementations where the serverConstructor is of the pattern "spring:{bean_name}"

    This is the easiest method and produces the best result. A Collection of Java Beans, such as EJB or Hibernate-managed beans, can be directly returned to Smart GWT as the result of a DMI method, without the need to create an intervening Data Transfer Object to express which fields should be delivered to the browser - instead, only the fields declared on the DataSource are returned to the browser (see dropExtraFields. In this integration scenario, the majority of the features of the Smart GWT Server framework still apply - see this overview.

    Note, there are special scoping considerations to bear in mind when using Spring-injected DataSources or DMIs - see this discussion of caching and thread-safety issues.

  • configure Spring to return XML or JSON responses: create variants on existing Spring workflows that use a different type of View in order to output XML or JSON data instead of complete HTML pages. The Smart GWT RestDataSource provides a standard "REST" XML or JSON-based protocol you can implement, or you can adapt generic DataSources to existing formats.

    In some Spring applications, all existing Spring workflows can be made callable by Smart GWT with a generic View class capable of serializing the Model to XML or JSON, combined with a Controller that always uses this View. Consider the following Java anonymous class, which uses the Smart GWT JSTranslater class to dump the entire Spring Model as a JSON response.

       new View() {
             public void render(Map model, HttpServletRequest request,
                                HttpServletResponse response) throws IOException {
                     final ServletOutputStream outputStream = response.getOutputStream();
                     response.setContentType("application/x-javascript");
                     outputStream.println(JSTranslater.get().toJS(model));
                     outputStream.close();
             }
             public String getContentType() {
                     return "application/x-javascript";
             }
       }
      

    If you use this approach, you do not need to install the Smart GWT server, and can deploy Smart GWT as simple web content (JS/media/HTML files). If you are already familiar with how to generate XML from objects that typically appear in your Spring Models, this may be the easiest path.

Using Spring Controllers with Smart GWT DMI

You can create a Controller that invokes standard Smart GWT server request processing, including DMI, like so:

  public class SmartGWTRPCController extends AbstractController
  {
      public ModelAndView handleRequest(HttpServletRequest request, 
                                        HttpServletResponse response)
          throws Exception
      {
          // invoke Smart GWT server standard request processing
          com.isomorphic.rpc.RPCManager.processRequest(request, response);
          return null; // avoid default rendering
      }
  }
  
This lets you use Spring's DispatchServlet, Handler chain and Controller architecture as a pre- and post-processing model wrapped around Smart GWT DMI.

Using Spring Transactions with Smart GWT DMI

You can make DMI's participate in Spring's transaction management scheme by setting the useSpringTransaction flag on your DataSources or OperationBindings. This makes your DMI method(s) transactional, and ensures that any DSRequests and Spring DAO operations executed within that DMI use the same Spring-managed transaction. See the documentation for useSpringTransaction for more details.

In Power Edition and above, Smart GWT Server has its own transaction management system. This allows you to send queues of DSRequests to the server, and the entire queue will be treated as a single database transaction. This is not the same thing as Spring transaction integration: Smart GWT's built-in transaction management works across an entire queue of DSRequests, whereas Spring transactions are specific to a Java method that has been marked @Transactional - the transaction starts and ends when the method starts and ends.

It is possible to have an entire Smart GWT queue - including any @Transactional DMIs that contain both Spring DAO operations and DSRequests - use the same Spring-managed transaction. To do this:

  • Create a new Spring service bean with a @Transactional method like this (note, the isolation level can vary as you please, but the propagation type must be REQUIRED to enable proper sharing of the transaction):
         @Transactional(isolation=Isolation.READ_COMMITTED, propagation=Propagation.REQUIRED)
         public class MyServiceBean {
      
             // invoke Smart GWT server standard request processing
             public void processQueue(RPCManager rpc) throws Exception {
                 rpc.processRPCTransaction();
             }
         }
  • Either: Subclass the com.isomorphic.servlet.IDACall servlet and override its processRPCTransaction method to inject the service bean you just created and invoke its transactional method. You will also have to change your web.xml file to point at this new servlet rather than IDACall
  • Or: Use a Spring Controller, as described in the section Using Spring Controllers with Smart GWT DMI, above. Just follow the instructions for using a Spring Controller, but have your handleRequest() implementation inject your service bean and invoke its transactional method, as described for the IDACall subclass approach
Whether you choose the IDACall or Spring Controller approach, the important thing is that the call to RPCManager.processRPCTransaction() takes place from within a @Transactional method of a Spring service bean. This will place the processing of the entire Smart GWT queue inside the transaction that is created by Spring to service that transactional method.

Using Spring DataSources with Smart GWT SQLDataSource

Smartclient SQL DataSources may be configured to obtain JDBC connections from the javax.sql.DataSource implementation provided by Spring context. Search for sql.MyDatabase.interface.type in SQL settings overview for the configuration details.

Spring Compatibility

Spring & Hibernate have gone through reworks recently in which backwards compatibility was lost, creating complexity and difficult tradeoffs for consumers of these libraries, where there may be conflicting requirements to use different, incompatible versions of those frameworks. We have tried to do the best we can in terms of supporting many possible combinations of versions, where feasible.

The Spring 5 framework integrated with Smart GWT is only compatible with Java 8+, so you can't use older version of Java together with Smart GWT's built-in Spring support, such as the "spring:" DMI target. If you have to use a Java version less than 8, please see the "Using Java version less than 8" section at the end of this document.

Using Hibernate 3 or 4 with Spring 5

The Spring 5 ships with Hibernate 5 support only, i.e. without built-in Hibernate 3 and 4 support it used to have.

Smart GWT provides "bridges" that allow Spring 5 to be used with Hibernate 3 or 4. To use this combination, include either isomorphic_spring_hibernate-core-6.5.3.Final.jar for Hibernate 3 support or isomorphic_spring_hibernate4.jar for Hibernate 4 support.

Smartclient bridge classes are based on Spring 4.3.26 org.springframework.orm.hibernate3 and org.springframework.orm.hibernate4 packages and are placed in corresponding packages: com.isomorphic.springhibernate3 and com.isomorphic.springhibernate4. So, for example, to configure managed Hibernate SessionFactory com.isomorphic.springhibernate3.LocalSessionFactoryBean class should be used instead of org.springframework.orm.hibernate3.LocalSessionFactoryBean class:

  <bean id="hbSpringSessionFactory"
        className="com.isomorphic.springhibernate3.LocalSessionFactoryBean">
      <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
  </bean>
  
Other than that the usage is the same.

Using Hibernate 5

Hibernate 5 is not yet supported by Smartclient, but it still may be used via custom DataSource implementation, as is demonstrated in ORM DataSource and Resusable ORM DataSource Showcase samples. Note that in this case Smartclient built-in Hibernate support would be lost and features like data pagination, server-side sorting and filtering, server summaries etc would also have to be implemented manually in custom DataSource if you need them.

Using Java version less than 8

With pre JDK8, you cannot use Spring 5 (according to Spring docs), so, you have to remove all Spring 5 related jars. Then, you could use Spring 4 or earlier, but without any of our framework support for Spring which, as of release 13.0, requires Spring 5+ (older releases work with Spring 4).

To remove Spring from the Smart GWT server all Spring JARs must be removed from your WEB-INF/lib server directory:

  • spring-aop-6.1.15.jar
  • spring-beans-6.1.15.jar
  • spring-context-6.1.15.jar
  • spring-context-support-5.3.9.jar
  • spring-core-6.1.15.jar
  • spring-expression-6.1.15.jar
  • spring-jdbc-6.1.15.jar
  • spring-orm-6.1.15.jar
  • spring-tx-6.1.15.jar
  • spring-web-6.1.15.jar
  • spring-webmvc-6.1.15.jar
  • isomorphic_spring.jar
  • isomorphic_spring_hibernate-core-6.5.3.Final.jar
  • isomorphic_spring_hibernate4.jar

and Spring configuration must be removed from your WEB-INF/web.xml:

  <!-- standard spring configuration -->
  <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>
  <listener>
      <listener-class>com.isomorphic.spring.ContextLoaderListener</listener-class>
  </listener>