<?xml version="1.0" encoding="UTF-8"?>
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="service-activator"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Service Activator</title>

  <section id="service-activator-introduction">
    <title>Introduction</title>
    <para>
      The Service Activator is the endpoint type for connecting any Spring-managed Object to an input channel so that
      it may play the role of a service. If the service produces output, it may also be connected to an output channel.
      Alternatively, an output producing service may be located at the end of a processing pipeline or message flow in
      which case, the inbound Message's "replyChannel" header can be used. This is the default behavior if no output
      channel is defined, and as with most of the configuration options you'll see here, the same behavior actually
      applies for most of the other components we have seen.
    </para>
  </section>

  <section id="service-activator-namespace">
    <title>Configuring Service Activator</title>
    <para>
      To create a Service Activator, use the 'service-activator' element with the 'input-channel' and 'ref' attributes:
      <programlisting language="xml">&lt;int:service-activator input-channel="exampleChannel" ref="exampleHandler"/&gt;</programlisting>
    </para>
    <para>
      The configuration above assumes that "exampleHandler" either contains a single method annotated with the
      @ServiceActivator annotation or that it contains only one public method at all. To delegate to an explicitly
      defined method of any object, simply add the "method" attribute.
      <programlisting language="xml">&lt;int:service-activator input-channel="exampleChannel" ref="somePojo" method="someMethod"/&gt;</programlisting>
    </para>
    <para>
      In either case, when the service method returns a non-null value, the endpoint will attempt to send the reply
      message to an appropriate reply channel. To determine the reply channel, it will first check if an
      "output-channel" was provided in the endpoint configuration:
      <programlisting language="xml">&lt;int:service-activator input-channel="exampleChannel" output-channel="replyChannel"
                   ref="somePojo" method="someMethod"/&gt;</programlisting>
      If no "output-channel" is available, it will then check the Message's <literal>replyChannel</literal> header
      value. If that value is available, it will then check its type. If it is a
      <interfacename>MessageChannel</interfacename>, the reply message will be sent to that channel. If it is a
      <classname>String</classname>, then the endpoint will attempt to resolve the channel name to a channel instance.
      If the channel cannot be resolved, then a <classname>ChannelResolutionException</classname> will be thrown.
      It it can be resolved, the Message will be sent there. This is the technique used for Request Reply messaging
      in Spring Integration, and it is also an example of the Return Address pattern.
    </para>
    <para>
      The argument in the service method could be either a Message or an arbitrary type. If the latter, then it will
      be assumed that it is a Message payload, which will be extracted from the message and injected into such service
      method. This is generally the recommended approach as it follows and promotes a POJO model when working with Spring
      Integration. Arguments may also have @Header or @Headers annotations as described in <xref linkend="annotations"/>
    </para>
    <note>
       The service method is not required to have any arguments at all, which means you
       can implement event-style Service Activators, where all you care about is an invocation of the service method,
       not worrying about the contents of the message. Think of it as a NULL JMS message. An example use-case for such an
       implementation could be a simple counter/monitor of messages deposited on the input channel.
    </note>
    <para>
      Using a "ref" attribute is generally recommended if the custom Service Activator handler implementation can be reused
      in other <code>&lt;service-activator&gt;</code> definitions. However if the custom Service Activator handler implementation
      is only used within a single definition of the <code>&lt;service-activator&gt;</code>, you can provide an inner bean definition:
<programlisting language="xml"><![CDATA[<int:service-activator id="exampleServiceActivator" input-channel="inChannel"
            output-channel = "outChannel" method="foo">
    <beans:bean class="org.foo.ExampleServiceActivator"/>
</int:service-activator>]]></programlisting>
    </para>
    <note>
    <para>
    Using both the "ref" attribute and an inner handler definition in the same <code>&lt;service-activator&gt;</code>
    configuration is not allowed, as it creates an ambiguous condition and will result in an Exception being thrown.
    </para>
    </note>
    
    <para>
    	<emphasis>Service Activators and the Spring Expression Language (SpEL)</emphasis>
    </para>
    
    <para>
    Since Spring Integration 2.0, Service Activators can also benefit from SpEL   
    (http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/expressions.html).
	</para>
	<para>
	For example, you may now invoke any bean method without pointing to the bean via a <code>ref</code> attribute or including it as an 
	inner bean definition. For example:
	
	<programlisting language="xml"><![CDATA[<int:service-activator input-channel="in" output-channel="out" 
	expression="@accountService.processAccount(payload, headers.accountId)"/>
	
	<bean id="accountService" class="foo.bar.Account"/>]]></programlisting>
	
	In the above configuration instead of injecting 'accountService' using a <code>ref</code> or as an inner bean,
	we are simply using SpEL's <code>@beanId</code> notation and invoking a method which takes a type compatible with Message payload. We
	are also passing a header value. As you can see, any valid SpEL expression can be evaluated against any content in the Message.
    For simple scenarios your <emphasis>Service Activators</emphasis> do not even have to reference a bean if all logic can be encapsulated 
    by such an expression.
    
    <programlisting language="xml"><![CDATA[<int:service-activator input-channel="in" output-channel="out" expression="payload * 2"/>]]></programlisting>
    In the above configuration our service logic is to simply multiply the payload value by 2, and SpEL lets us handle it relatively easy.
    
    </para>
    
  </section>

</section>
