Spring

Spring at GID

Overview

Why use Spring at all?

  • What are the system design concerns that motivate using Spring in the first place?
  • How does Spring generally fit in the technology selection thinking?
    • Spring is a "facilities"/"application infrastructure" component in the design.
    • It can be helpful to think of Spring as a JEE Application Server

Features/Facilities

  • Dependency Injection (DI) container
  • XML-Schema-based configuration (using XML namespaces to make Spring config more terse and readable.)
  • Light-weight Aspect-Oriented Programming support
  • JEE Container-like services:
    • Persistence Integration API ("template"s that do boilerplate work; JDBC, Hibernate and JDO are supported).
    • Transaction Integration API
    • Java Messaging Service Integration APIs

Themes:

  • Exception Translation
    • interprets database errors into more useful Exception types.
    • Converting checked Exceptions in various APIs to RuntimeExceptions (simplifies application code because, face it, how often can application code handle specific exceptions? Often you want to handle the fact that an error occurred and clean-up resources gracefully).

Transaction Support

Why use Spring for Transactions?

* Abstract to the concept of just "Transaction"; pull away the flavors: Global vs. local; Container Managed (obtained using JNDI) vs. hand-rolled;
* Enjoy the benefits of container-managed transactions w/o the container: declarative,

  • Base concept: PlatformTransactionManager; this is a transaction "strategy"
    • Can the TxMgr participate in a global transaction?

JMS Support

Why use Spring for JMS?

  • In General…
  • For sending…
  • For receiving…

Core Concepts

  • Templates for doing JMS that integrates well with all other JMS features.
  • Provides abstraction from 1.0.2 and 1.1 JMS specs
  • Exception Translation
  • Message Listen Container
  • Destination Management
  • Integration with Spring Transactions

JmsTemplate

  • doSend(…) — send a single JMS message
    • MessageCreator — your callback that will create a java.jms.Message given a java.jms.Session
  • doReceive(…) — accept/receive a single JMS message()
  • browse(…) — peek at the JMS destination
  • execute(…)
    • SessionCallback — for modifying the session
    • ProducerCallback — typically for sending multiple messages on the same session+provider
  • General params:
    • deliveryMode = {PERSISTENT, NON_PERSISTENT}
    • messageIdsEnabled : boolean
    • messageTimestampEnabled : boolean
    • priority : integer — priority of messages send from this template
    • pubSubDomain : boolean (default=false;JmsTemplate102 only ) — if false, template assumes Destination is a Queue; if true, assumes the Destination is a Topic.
    • defaultDestination — name of the destination to use if none is supplied/resolved.

Once configured, the JmsTemplate is thread-safe: it can be used by multiple senders concurrently.

ConnectionFactory

Ultimate, the ConnectionFactory implementation comes from the underlying JMS Provider. This is typically done via a JNDI lookup.

  • SingleConnectionFactory — wraps a ConnectionFactory so that one single connection is returned by all calls to ConnectionFactory.createConnection().

Destination Management

  • "Destination" as in the JMS concept, being an abstraction of either a Queue or a Topic.
  • Basically, the JmsTemplate delegates resolution of the target Destination via a "resolution strategy" called DestinationResolver.
    • DynamicDestinationResolver (default)
    • JndiDestinationResolver — looks-up the Queue or Topic in a JNDI tree.
  • The attitude, here, is that it's not uncommon to not know the name of the Queue or Topic at build time. So, provide a resolver so that we can do this at runtime.

Message Listener Containers

Message Listener Container is an intermediary between the JMS Destination and your java.jms.MessageListener (very often a MDP).

  • SimpleMessageListenerContainer — establishes a fixed number of connections to the JMS Provider. Does not support hooking-up to externally managed transactions. //
  • DefaultMessageListenerContainer (most commonly used) — //supports dynamic session management (for runtime-tuning); supports doing message processing in the context of an XA transaction.
  • ServerSessionMessageListenerContainer — requires the provider support runtime tuning (via the ServerSessionPool SPI); also supports external transaction participation.

Transactional JMS

Transactional GETs

  • For local transactions, configure the MessageListenerContainer's sessionTransacted = true.
  • For global transactions, configure a JtaTransactionManager (which by default delegates to the JEE container's transaction subsystem) and set the MessageListenerContainer's tranasactionManager property to that JtaTransactionManager instance.

Transactional PUTs

  • For local transactions, configure the underlying ConnectionFactory with a JmsTransactionManager; This PlatformTransactionManager binds the Connection/Session to Thread Local Storage (TLS); the JmsTemplate will automatically detect this and use the JMS API, internally, correctly so as to perform transactional JMS.
  • For global transactions, similar thing.
    • the ConnectionFactory must XA-capable
    • you must configure the ConnectionFactory's transactionManager to reference the JtaTransactionManager.

Message-Driven POJOs (and other MessageListeners)

  • SessionAwareMessageListener is a Spring-provided interface for allowing the MDP/MessageListener to be able to use the same Session to send messages/responses to received messages.
  • MessageListenerAdapter — a Spring bean that fronts for a genuine POJO. The adapter has the onMessage() method that delegates to your POJO. You configure which method is called by setting the "defaultListenerMethod" property on the adapter.
    • if your method has a return value, you can configure the adapter to send a response message (to the Destination specified in the JMS Reply-to field; or to the default Destination that you configure on the Adapter).

JCA Support

With Spring, you can configure a JMS Endpoint for a JCA Resource Adapter and hook-up a MessageListener to it. To do this, you need to:

  1. Configure the ResourceAdapter (using org.springframework.jca.support.ResourceAdapterFactoryBean)
  2. Configure a JmsMessageEndpointManager (from org.springframework.jms.listener.endpoint) with:
    • the Resource Adapter
    • Activation Specification Config
    • a MessageListener (many?)
  • Spring provides an Activation Spec configuration abstraction (org.springframework.jms.listener.endpoint.JmsActivationSpecConfig) which will attempt to determine the JCA's ActivationSpec configuration object (in ActiveMQ, for example, it's an instance of org.apache.activemq.ra.ActiveMQActivationSpec). This allows you to be JCA provider agnostic with Activation config.

XML-Schema-based Config

There is a XML namespace for the Spring JMS that greatly reduce the amount of Spring configuration XML required: http://www.springframework.org/schema/jms/spring-jms-2.5.xsd

Outstanding Questions/Research

  • How does JCA Message Endpoint management work? What's up with Activation Specification config? What is that?
  • (Spring Reference, 19.2.2) — there's a mention of how J2EE containers require the ConnectionFactory be referenced as a "resource-ref" in the EJB/Servlet deployment descriptor in order for that ConnectionFactory to participate in CMT and connection pooling/session pooling. Is this true for WAS 5.1? How about for JBoss 4.2.x? What does this mean in terms of how ConnectionFactory's should be configured?
  • Why are Destinations (Queues and Topics) JNDI-registered administered objects? Aren't they just names of things?
  • Seems like there is a lot of functionality in the MessageListenerAdapter. What are all of the features of this very useful class?

References

*

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License