4.2. Configuring a Remoting Service and a Destination

You were introduced to the message broker in the last section. By now, you know that the message broker is the hub of all activity in BlazeDS. The message broker receives and processes messages from the clients to the BlazeDS endpoints and passes them down to the remoting service. It also returns the results to the client using the reverse route. Therefore, almost all communication within BlazeDS gets routed through the message broker. On startup, the message broker is bootstrapped by the message broker Servlet. This activity of bootstrapping and initializing the message broker involves reading the configurations for the associated endpoints, services, destinations, and adapters. Based on the configurations, the associated artifacts and components are instantiated and initialized and hooked on to the message broker.

Such configuration parameters for the message broker and its associated artifacts are specified in the services-config.xml configuration file. This configuration file, by default, resides in the WEB-INF/flex folder within the BlazeDS distribution. As a starting point, the important configuration elements pertaining to a remoting service and a destination are shown in Figure 4-3.

From the earlier chapters, you know that services-config.xml is broken down into multiple XML files for convenience. The common configuration remains in services-config.xml, and the additional XML files contain elements that pertain to the proxy service, the remoting service, and the messaging service. In the commercial alternative to BlazeDS, that is, LifeCycle Data Services, or LCDS, there is also a file for the data management service. Each of these additional XML files is included in services-config.xml by reference. The file that contains remoting-service-specific configuration is called remoting-config.xml. So, all the important remoting-related configuration elements shown in Figure 4-3 are included in remoting-config.xml.

To explain these configuration elements, let's walk through an example. A possible remoting-config.xml configuration is:

<service id="aRemotingService"
    class="flex.messaging.services.RemotingService">

    <adapters>
        <adapter-definition id="java-object"
            class="flex.messaging.services.remoting.adapters.JavaAdapter"
            default="true"/>
    </adapters>

    <default-channels>

<channel ref="myAMFChannel"/>
    </default-channels>

    <destination id="myPOJODestination">
        <properties>
            <source>problazeds.ch04.MyPOJO</source>
            <scope>session</scope>
        </properties>
    </destination>
</service>

Figure 4.3. Figure 4-3

This configuration example wraps all configurations within a <service> tag. Each service in BlazeDS follows this idiom, where the service tag is the highest level, enclosing element for a service definition. An adapter, a channel, and a destination are associated with a remoting service. In the preceding example, an AMFChannel is used for the remoting service. The service itself binds to a POJO, which serves as the destination. A Java adapter is used to talk to the POJO and works just fine.

The destination is configured with the help of properties, two of which are shown in the preceding example. These are source and scope. The source property specifies the fully qualified name of the POJO. This POJO should be on the web application classpath for BlazeDS to load it; that is, it should be either within the WEB-INF/classes folder or be packed in a Java archive file and reside within the WEB-INF/lib folder. The scope specifies the instantiation policy, the visibility, and the lifespan for the POJO instance. The scope can take any of the following three possible values:

  • request

  • session

  • application

If you are familiar with web application development, then you probably already know what these terms imply. However, for completeness, I will define these terms here as well.

A request scope implies that the instance is relevant for a request only. This means for each request, or incoming call, a new instance of the object is created. So, a POJO with request scope is instantiated by BlazeDS every time there is a new request. A request scope is good when no state needs to be maintained on the server. A request scope is the default scope.

A session scope implies that the instance is relevant for a session. All requests originating from the same browser or user agent fall within the same session. This means requests from different tabs of a browser also get counted within the same session. So, if you open up a Flex application in two different adjoining tabs of a browser and make the same remoting service call, the same POJO will be accessed, if it is scoped to be relevant for a session.

The third alternative is to share the same instance throughout the application. This implies two or more requests from two or more separate browsers or user agents see the same instance of the object. This third type of scope is the application scope.

The configuration discussed so far is typically all that's required as far a standard POJO-based destination goes. Sometimes though, additionally, you may want to do any or all of the following:

  • Secure a destination and restrict access to it

  • Intercept all calls made to a particular remoting service

  • Log all calls to a particular destination

  • Talk to a remoting service using a text-based protocol

  • Converse with a remoting service over HTTPS

  • Define custom scope for destinations

  • Use managed objects side by side with POJOs

So, I will take each in turn and explain how one could include these additional features. In this section, the focus is on how to configure such a feature over and above the standard configuration. In some cases configuration alone may not be sufficient, and one may need to extend the standard classes with custom implementations. In such cases, I will restrict the discussion to configuration for now and will talk about the custom extensions later, in the section titled "Value Additions on Simple Remoting" and in the following chapters.

4.2.1. Securing Destinations

In Chapter 3, you learned the fundamentals of applying security and access control to destinations. All those concepts apply to remoting services as much as they apply to proxy services.

So, you can define a basic or custom authentication scheme and have your users authenticate to access a remoting destination. You could associate the authentication on either a per-client or a per-session basis. When authentication is configured on a per-client basis, you need to authenticate the user separately for each browser tab and also when the browser is refreshed.

Apart from authentication and the role-based authorization security constraint, access to specific methods can be controlled at the destination level. Simple method-level access control can be applied using either of the following mechanisms:

  • Include all allowed methods in the include-methods list

  • Exclude restricted methods by including them in the exclude-methods list

Both these lists, that is, include-methods and exclude-methods, can be specified within the properties tag of a destination. The include-methods list also allows a security constraint to be attached to an individual method and allows fine-grained security implementation. Use of the exclude-methods list makes the most sense when access to only a few methods is restricted and there is no need to specify security at the method level.

Listing 4-1 illustrates a sample configuration that provides a method-level security constraint. The contextual explanation of the listed configuration follows the listing itself.

Example 4.1. A Sample Security Configuration for a Remoting Service Destination
<service id="aRemotingService"
    class="flex.messaging.services.RemotingService">

    <adapters>
        <adapter-definition id="java-object"

class="flex.messaging.services.remoting.adapters.JavaAdapter"
            default="true"/>
    </adapters>

    <default-channels>
        <channel ref="myAMFChannel"/>
    </default-channels>

    <destination id="myPOJODestination">
        <properties>
            <source>problazeds.ch04.MyPOJO</source>
            <scope>session</scope>
            <include-methods>
                <method name="methodA"/>
                <method name="methodB" security-constraint="admin-users"/>
            </include-methods>
        </properties>
        <security>
            <security-constraint ref="regular-users"/>
        </security>
    </destination>

    <destination id="mySecondPOJODestination">
        <properties>
            <source>problazeds.ch04.AnotherPOJO</source>

<scope>request</scope>
        </properties>
    </destination>

    <default-security-constraint ref="admin-users"/>

</service>

The preceding listing depicts four different aspects of securing a destination. These are:

  • Security can be defined inline, within a destination configuration. Notice the presence of an inline security definition for regular users within myPOJODestination.

  • Method-level security constraint can be defined for methods in the include-methods list. Only admin-users are allowed access to methodB of myPOJODestination. The security definition for admin-users is defined in services-config.xml and maps to either a basic or custom authentication scheme and a role. Refer to the section titled "Access Control to Proxy Destinations" from Chapter 3 for details on how to configure a security in services-config.xml.

  • The security constraint at a destination and a method level can be different. The method-level constraint applies in precedence to the destination-level constraint for the particular method. This outcome is logical as the method-level constraint is more granular than the one at the destination level.

  • Default security constraint can be defined at the service level. Such a constraint applies to all destinations that do not define a security constraint. In the listing above, mySecondPOJODestination uses the default security constraint, since it doesn't define one of its own.

With these out-of-the-box facilities you can secure destinations and restrict access to specific roles and user groups without much trouble. You can also implement custom authentication and authorization schemes, which may not be available off the shelf, and use them with BlazeDS. The section titled "Value Additions on Simple Remoting" explains how to create such custom authentication and authorization schemes.

BlazeDS supports Role-Based Access Control (RBAC), which is a dominant style of access control within enterprise applications, so its security architecture works well in most situations. However, RBAC is not the only form of access control and when alternatives are required customization could involve some heavy lifting and major modifications. Read the note on access control techniques to understand the alternatives to RBAC.

Access Control Techniques

There are two important participants in any system: subject and object. A subject is an entity that can carry out tasks and an object is a resource that may need controlled access. Tasks carried out by a subject impacts the concerned objects.

Access to objects can be controlled by using one of the two popular models: capability-based or Access Control List (ACL) based. In capability-based models the access is restricted to entities who own the capability, which can be thought of as an access key. In ACL-based models, access is restricted to subjects on the list.

To implement access control, software systems typically use one of the following three techniques:

  • Discretionary Access Control (DAC)

  • Mandatory Access Control (MAC)

  • Role-Based Access Control (RBAC)

In a DAC-based system, the owner of an object decides which subjects get control over the objects. The owner also decides the type of control a subject gets. An object's owner often is the creator of that object, and a typical example of a DAC-based system is the file system.

MAC is relevant where fine-grained access control is desired. In a MAC-based system, the access control is defined at a system level and the owner does not define the access control policy. Often, sensitivity-level labels are attached to subjects and objects. A subject can access only those objects that fall within the same or lower sensitivity level than the subject's sensitivity level. MAC-based systems are also rule-based access control systems. In the simplest case, the sensitivity matching rules grant and deny access. For complicated scenarios that could involve multiple subjects and objects at different levels of sensitivity, the rules could be complex. Sometimes, Lattice-Based Access Control (LBAC) can be used in mandatory access control systems for such complex scenarios. For example, two subjects, A and B, are given access to an object only if the greatest lower bound of the sensitivity levels of these two subjects matches with the required sensitivity level for the object.

RBAC is the most popular form of access control in enterprise systems. Permissions are clubbed together in a role and users are assigned to the role. Roles can have hierarchical structures, and users can be assigned to roles based on additional rules.


In some cases, you may not only want to secure the remoting service but may also want to intercept all calls to it. The reasons for such an interception could range from auditing to enrichment, through rule-based filters.

Next, we explore the ways to intercept calls to a remoting service destination.

4.2.2. Intercepting and Logging Calls to a Remoting Service

All calls to a BlazeDS based server-side service can be intercepted using Servlet filters. BlazeDS is a Java Servlets based web application and configuring Servlet filters to work with BlazeDS is easy. For example you could set up a Servlet filter to intercept all calls to the BlazeDS message broker as follows:

<filter>
        <filter-name>AFilter</filter-name>
        <filter-class>org.shanky.filters.AUsefulServletFilter</filter-class>
</filter>

    <filter-mapping>

<filter-name>AFilter</filter-name>
        <url-pattern>/messagebroker/*</url-pattern>
    </filter-mapping>

In addition, calls can be logged both on the client and on the server.

For auditing, monitoring, and debugging, the built-in logging facility is fairly robust and easy to configure. The following can be configured for the logging facility:

  • Logging target—You can specify that the log output be written to the console or be directed to the default logger configured for the Servlet container in which BlazeDS resides.

  • Logging level—You can set the logging level to All, Debug, Error, Info, None, or Warn. The logging level determines what types of messages are logged. Warn shows both warning and error messages, Error shows error messages only, and Debug shows debugging messages apart from warnings and errors. Info shows general information messages, in addition to errors. All and None show all and nothing, respectively.

  • Log content metadata—You can specify to include the following:

    • Category—The BlazeDS subsystem or area that generated the message

    • Date—Log message date

    • Time—Log message time

    • Level—The chosen logging level

    • Prefix—a string to be prefixed to log messages

In addition, you can filter the messages and log only those that match particular category. For example, all messages generated by the remoting-related artifacts only, such as RemotingService and RemotingDestination, can be logged using the Service.Remoting filter. This can be very useful, especially if your system is complex and you only want to focus on log messages generated by a part of the system. Finer-grained logging at the level of each named destination can be a further enhancement on this feature. In Chapter 8, I show how such an enhancement can be included in BlazeDS.

Before we jump to the next topic on the list, let's look through a sample logging configuration that captures only messages generated by the remoting service. Here it is:

<logging>
    <target class="flex.messaging.log.ConsoleTarget" level="Debug">
        <properties>
            <prefix>[Professional BlazeDS Chapter 4]</prefix>
            <includeDate>true</includeDate>
            <includeTime>true</includeTime>
            <includeLevel>true</includeLevel>
            <includeCategory>false</includeCategory>
        </properties>
        <filters>
            <pattern>Service.Remoting</pattern>
        </filters>
    </target>
</logging>

4.2.3. Talking AMFX

AMF 3 is a message format that encodes objects to a binary format and can be used in conjunction with HTTP to exchange data between a Flex application and a server. Such a server could be a Java server that uses BlazeDS. Apart from the binary option, it's also possible to convert the AMF 3 messages to XML and then exchange them over the wire. AMF represented in XML is AMFX. AMFX is a text-based data exchange.

Use AMFX with remote object over alternatives like XML over HTTPService, especially if BlazeDS is already part of the infrastructure. Using AMFX with remote objects implies auto-translation of Java types to AS3 and vice-versa without the need of explicit hand-coded marshaling and un-marshaling as with XML over HTTPService. Besides, it allows seamless swap in of AMF in place of AMFX if need be.

To transmit data using AMFX you need to use the HTTPChannel and the corresponding HTTPEndpoint. Your services-config.xml file probably already includes a channel definition for the HTTPChannel and HTTPEndpoint pair as follows:

<channel-definition id="my-http" class="mx.messaging.channels.HTTPChannel">
            <endpoint url="http://{server.name}:{server.port}/{context.root}/
              messagebroker/http" class="flex.messaging.endpoints.HTTPEndpoint"/>
            <properties>
                <piggybacking-enabled>true</piggybacking-enabled>
                <invalidate-session-on-disconnect>true</invalidate-session-on-
                  disconnect>
            </properties>
        </channel-definition>

To use this channel just reference the channel by its name within the remoting service configuration.

The AMFX channel and endpoint are supported by a set of serialization and deserialization classes that convert Java data types to AS3 and back via AMF in XML. The AmfxTypes interface provides the signature for the class that enables the XML representation of AMF3. AmfxOutput is the class that serializes Java data types to AS3 via AMFX. AmfxMessageDeserializer is a SAX based AMFX parser. AmfxInput provides the context for AmfxMessageDeserializer.

The AMFX channel is called the HTTPChannel, although AMFXChannel would have been a better name for it. The AMFChannel also uses HTTP for data exchange and explicitly calling the AMFX channel the HTTPChannel almost misleads developers to believe that the AMFChannel probably does not use HTTP. Also, the HTTPChannel is sometimes confused with a generic text-based channel for object data exchange, which is not true. It specifically exchanges data as AMFX. If you choose to encode your objects using formats like XML-RPC or JSON, or any format other than AMFX, then you need to write a custom channel and endpoint pair with its own set of classes for serialization and deserialization.

Whether you're using AMF or AMFX, you may want to leverage the HTTPS protocol instead of plain HTTP and prevent the data exchange from being snooped into by intruders. That's what comes next.

4.2.4. Using HTTPS

Using an HTTPS channel in BlazeDS merely requires a simple configuration change. Just remember to use the secure HTTPS channels for AMF and AMFX. HTTPS channels are defined in services-config.xml like so:

<channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
            <endpoint url="https://{server.name}:{server.port}/
              {context.root}/messagebroker/amfsecure"
              class="flex.messaging.endpoints.SecureAMFEndpoint"/>
            <properties>
                <add-no-cache-headers>false</add-no-cache-headers>
                <connect-timeout-seconds>5</connect-timeout-seconds>
            </properties>
        </channel-definition>

    <channel-definition id="my-secure-http" class="mx.messaging.
      channels.SecureHTTPChannel">
            <endpoint url="https://{server.name}:{server.port}/
              {context.root}/messagebroker/httpsecure"
              class="flex.messaging.endpoints.SecureHTTPEndpoint"/>
            <properties>
                <add-no-cache-headers>false</add-no-cache-headers>
            </properties>
        </channel-definition>

These HTTPS channels exchange data over HTTP, using Secure Socket Layer (SSL). In LifeCycle Data Services, the data push channel based on RTMP uses Transport Layer Security (TLS). If you need to use TLS, you will have to handcraft those channels for your use.

If you don't know the difference between SSL and TLS, then you may benefit from reading the "SSL vs. TLS" sidebar in this chapter.

SSL vs. TLS

SSL, or Secure Socket Layer, is a protocol for secure communication between a client and server. SSL was invented by Netscape and has gone a few revisions up to its current version 3.0. TLS, which stands for Transport Layer Security, supersedes SSL as the current-generation protocol for secure communication between a client and a server. The TLS standard was formed through an IETF initiative: RFC 2246. You can access the RFC 2246 documentation at www.ietf.org/rfc/rfc2246.txt. Although similar in intent, SSL and TLS do not interoperate. Systems using TLS, however, can be downgraded to work as SSL 3.0.


Earlier when I listed a few extension and exception cases, I also included situations that involve custom scoping and managed objects. Both these topics are discussed in the following chapters. Managed objects are the central theme of Chapter 5. Custom scopes are touched upon in the context of the Java Persistence API (JPA) and Hibernate in Chapter 7.

At this point, our coverage of remoting service configuration is fairly complete. Nonetheless, you will continue to incrementally learn more about it as you explore the customization and extension mechanisms in the following chapters. Next, we get under the hood of the serialization and deserialization story that forms the backbone of the data services' features.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.154.252