2. Spring Services

Introduction

Granite Data Services supports out-of-box Spring framework integration. You can easily power your Java destinations with all Spring features including Inversion of Control/Dependency Injection, AOP interceptors, transaction management, etc.

GDS/Spring also fully support Acegi security system.

For a basic sample with Granite DS/Spring/Acegi/EJB 3 entity beans working together, download graniteds-spring-ejb3-1.1.0.zip and import it as a new Eclipse project.

Spring Services Configuration

The first step is to configure your Spring destinations:

services-config.xml
<?xml version="1.0" encoding="UTF-8"?>

<services-config>

    <services>
        <service
            id="granite-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="test">
                <channels>
                    <channel ref="my-graniteamf"/>
                </channels>
                <properties>
                    <factory>springFactory</factory>
                    <source>springBean</source>
                </properties>
                <security>
                    <security-constraint>
                        <auth-method>Custom</auth-method>
                        <roles>
                            <role>ROLE_USER</role>
                            <role>ROLE_ADMIN</role>
                        </roles>
                    </security-constraint>
                </security>
            </destination>
        </service>
    </services>

    <factories>
        <factory id="springFactory"
            class="org.granite.messaging.service.SpringServiceFactory" />
    </factories>

    <channels>
        <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">
            <endpoint
                uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>

</services-config>

Some Comments:

<properties>...</properties>

This block tells GDS to use factory class springFactory, see below, to instantiate current destination.
Tag <source> names a Spring bean, used to represent your destination.

<security>...</security>

This block, which is optional, tells the GDS Acegi security service, see below, to check for required roles when accessing the test destination. See the acegiSecurityContext.xml file in graniteds-spring-ejb3-1.1.0.zip for role configuration.

<factories>...</factories>

This block declares a Spring factory which is used to instantiate your destinations.

You may also customize your granite-config.xml in order to use automated externalization, etc.

Acegi Security Service Configuration

To enable Acegi security, you must put a declaration in granite-config.xml:

<granite-config>
   ...
   <!--
    ! Use Acegi based security service.
    !-->
    <security type="org.granite.messaging.service.security.AcegiSecurityService"/>

</granite-config>

You may then secure your Flex destinations as shown earlier. Please refer to Acegi documentation for specific configuration details.

General Web Configuration (web.xml)

In order to initialize Spring and Acegi security, you must also customize your web.xml as follows:

<web-app version="2.4" ...>
    ...
    <!-- Path to Spring config -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/conf/applicationContext.xml,
            /WEB-INF/conf/acegiSecurityContext.xml
        </param-value>
    </context-param>

    <!-- Spring listener -->
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <!-- Spring listener for web-scopes (request, session) -->
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>

    <filter>
        <filter-name>Acegi Filter Chain Proxy</filter-name>
        <filter-class>
            org.acegisecurity.util.FilterToBeanProxy
        </filter-class>
        <init-param>
            <param-name>targetBean</param-name>
            <param-value>filterChainProxy</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>Acegi Filter Chain Proxy</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

For a full example, please download graniteds-spring-ejb3-1.1.0.zip.

Automatic Configuration of Destinations

It is possible to instruct GraniteDS to automatically search for Spring destinations in the classpath by:

  • Enabling the automatic scanner :
    <granite-config scan="true">
    </granite-config>
    
  • Adding a META-INF/services-config.properties file in all jars containing Spring services
  • Annotating the Spring service with org.granite.messaging.service.annotations.RemoteDestination
    @Service("personService")
    @RemoteDestination(id="person", source="personService", securityRoles={"user","admin"})
    public class PersonServiceBean implements PersonService {
      ...
    }
    

The annotation supports the following attributes:

  • id is mandatory and is the destination name
  • source is mandatory and should be the name of the Spring component
  • service is optional if there is only one service for RemotingMessage defined in services-config.xml. Otherwise this should be the name of the service.
  • channel is optional if there is only one channel defined in services-config.xml. Otherwise this should be the id of the target channel.
  • channels may be used instead of channel to define a failover channel.
  • factory is optional if there is only one factory in services-config.xml. Otherwise this should be the factory id.
  • securityRoles is an array of role names for securing the destination.

As shown below, the service, factory and channel sections are still required in your services-config.xml file, but the service part is shortened by removing all destination configurations.

This requires a little more work on the Flex client because of the absence of destination definitions in services-config.
You then have to create your RemoteObjects with one of the following ways:

srv.endpoint = ServerConfig.getChannel("my-graniteamf").endpoint;
srv.destination = "personService";
srv.channelSet = new ChannelSet();
srv.channelSet.addChannel(ServerConfig.getChannel("my-graniteamf"));
srv.destination = "personService";
srv.channelSet = new ChannelSet();
srv.channelSet.addChannel(ServerConfig.getChannel("my-graniteamf"));

Browse Space

- Pages
- Blog
- Labels
- Attachments
- Bookmarks
- Mail
- Advanced

Explore Confluence

- Popular Labels
- Notation Guide

Your Account

Log In

Other Features

Add Content

- Add Comment


SourceForge.net Logo
Copyright © 2007-2008 Adequate Systems. All Rights Reserved.