Fuse ESB

Developing Apache CXF Interceptors

Version 4.4.1

Sept. 2011
Trademark Disclaimer
Third Party Acknowledgements

Updated: 06 Jun 2013

Table of Contents

1. Interceptors in the Fuse Services Framework Runtime
2. The Interceptor APIs
3. Determining When the Interceptor is Invoked
Specifying an interceptor's phase
Constraining an interceptors placement in a phase
4. Implementing the Interceptors Processing Logic
Processing messages
Unwinding after an error
5. Configuring Endpoints to Use Interceptors
Deciding where to attach interceptors
Adding interceptors using configuration
Adding interceptors programmatically
Using the interceptor provider API
Using Java annotations
6. Manipulating Interceptor Chains on the Fly
A. Fuse Services Framework Message Processing Phases
B. Fuse Services Framework Provided Interceptors
Core Fuse Services Framework Interceptors
Front-Ends
Message bindings
Other features
C. Interceptor Providers
Index

List of Figures

1.1. Fuse Services Framework interceptor chains
3.1. An interceptor phase
4.1. Flow through an interceptor

List of Tables

5.1. Interceptor chain configuration elements
5.2. Interceptor chain annotations
A.1. Inbound message processing phases
A.2. Inbound message processing phases
B.1. Core inbound interceptors
B.2. Inbound JAX-WS interceptors
B.3. Outbound JAX-WS interceptors
B.4. Inbound JAX-RS interceptors
B.5. Outbound JAX-RS interceptors
B.6. Inbound SOAP interceptors
B.7. Outbound SOAP interceptors
B.8. Inbound XML interceptors
B.9. Outbound XML interceptors
B.10. Inbound CORBA interceptors
B.11. Outbound CORBA interceptors
B.12. Inbound logging interceptors
B.13. Outbound logging interceptors
B.14. Inbound WS-Addressing interceptors
B.15. Outbound WS-Addressing interceptors
B.16. Inbound WS-RM interceptors
B.17. Outbound WS-RM interceptors

List of Examples

2.1. Base interceptor interface
2.2. The phase interceptor interface
3.1. Setting an interceptor's phase
3.2. Methods for adding an interceptor before other interceptors
3.3. Specifying a list of interceptors that must run after the current interceptor
3.4. Methods for adding an interceptor after other interceptors
3.5. Specifying a list of interceptors that must run before the current interceptor
4.1. Getting the message exchange
4.2. Getting messages from a message exchange
4.3. Checking the direction of a message chain
4.4. Example message processing method
4.5. Handling an unwinding interceptor chain
5.1. Attaching interceptors to the bus
5.2. Attaching interceptors to a JAX-WS service provider
5.3. The interceptor provider interface
5.4. Attaching an interceptor to a consumer programmatically
5.5. Attaching an interceptor to a service provider programmatically
5.6. Attaching an interceptor to a bus
5.7. Syntax for listing interceptors in a chain annotation
5.8. Attaching interceptors to a service implementation
6.1. Method for getting an interceptor chain
6.2. Methods for adding interceptors to an interceptor chain
6.3. Adding an interceptor to an interceptor chain on-the-fly
6.4. Methods for removing interceptors from an interceptor chain
6.5. Removing an interceptor from an interceptor chain on-the-fly

When a Fuse Services Framework developed consumer invokes a remote service the following message processing sequence is started:

When a Fuse Services Framework developed service provider receives a request from a consumer, a similar process takes place:

Developing an interceptor, regardless of its functionality, always follows the same basic procedure:

  1. Determine which abstract interceptor class to extend.

    Fuse Services Framework provides a number of abstract interceptors to make it easier to develop custom interceptors.

  2. Determine the phase in which the interceptor will run.

    Interceptors require certain parts of a message to be available and require the data to be in a certain format. The contents of the message and the format of the data is partially determined by an interceptor's phase.

  3. Determine if there are any other interceptors that must be executed either before or after the interceptor.

    In general, the ordering of interceptors within a phase is not important. However, in certain situations it may be important to ensure that an interceptor is executed before, or after, other interceptors in the same phase.

  4. Implement the interceptor's message processing logic.

  5. Implement the interceptor's fault processing logic.

    If an error occurs in the active interceptor chain after the interceptor has executed, its fault processing logic is invoked.

  6. Attach the interceptor to one of the endpoint's interceptor chains.

All of the interceptors in Fuse Services Framework implement the base Interceptor interface shown in Example 2.1.


The Interceptor interface defines the two methods that a developer needs to implement for a custom interceptor:

handleMessage()

The handleMessage() method does most of the work in an interceptor. It is called on each interceptor in a message chain and receives the contents of the message being processed. Developers implement the message processing logic of the interceptor in this method. For detailed information about implementing the handleMessage() method, see Processing messages.

handleFault()

The handleFault() method is called on an interceptor when normal message processing has been interrupted. The runtime calls the handleFault() method of each invoked interceptor in reverse order as it unwinds an interceptor chain. For detailed information about implementing the handleFault() method, see Unwinding after an error.

Most interceptors do not directly implement the Interceptor interface. Instead, they implement the PhaseInterceptor interface shown in Example 2.2. The PhaseInterceptor interface adds four methods that allow an interceptor the participate in interceptor chains.


When developing a custom interceptor, the first thing to consider is where in the message processing chain the interceptor belongs. The developer can control an interceptor's position in the message processing chain in one of two ways:

  • Specifying the interceptor's phase

  • Specifying constraints on the location of the interceptor within the phase

Typically, the code specifying an interceptor's location is placed in the interceptor's constructor. This makes it possible for the runtime to instantiate the interceptor and put in the proper place in the interceptor chain without any explicit action in the application level code.

One issue that arises when developing an interceptor is that the data required by the interceptor is not always present. This can occur when one interceptor in the chain consumes message data required by a later interceptor. Developers can control what a custom interceptor consumes and possibly fix the problem by modifying their interceptors. However, this is not always possible because a number of interceptors are used by Fuse Services Framework and a developer cannot modify them.

An alternative solution is to ensure that a custom interceptor is placed before any interceptors that will consume the message data the custom interceptor requires. The easiest way to do that would be to place it in an earlier phase, but that is not always possible. For cases where an interceptor needs to be placed before one or more other interceptors the Fuse Services Framework's AbstractPhaseInterceptor class provides two addBefore() methods.

As shown in Example 3.2, one takes a single interceptor id and the other takes a collection of interceptor ids. You can make multiple calls to continue adding interceptors to the list.


As shown in Example 3.3, a developer calls the addBefore() method in the constuctor of a custom interceptor.


Tip

Most interceptors use their class name for an interceptor id.

Another reason the data required by the interceptor is not present is that the data has not been placed in the message object. For example, an interceptor may want to work with the message data as a SOAP message, but it will not work if it is placed in the chain before the message is turned into a SOAP message. Developers can control what a custom interceptor consumes and possibly fix the problem by modifying their interceptors. However, this is not always possible because a number of interceptors are used by Fuse Services Framework and a developer cannot modify them.

An alternative solution is to ensure that a custom interceptor is placed after the interceptor, or interceptors, that generate the message data the custom interceptor requires. The easiest way to do that would be to place it in a later phase, but that is not always possible. The AbstractPhaseInterceptor class provides two addAfter() methods for cases where an interceptor needs to be placed after one or more other interceptors.

As shown in Example 3.4, one method takes a single interceptor id and the other takes a collection of interceptor ids. You can make multiple calls to continue adding interceptors to the list.


As shown in Example 3.5, a developer calls the addAfter() method in the constuctor of a custom interceptor.


Tip

Most interceptors use their class name for an interceptor id.

Figure 4.1 shows the process flow through an interceptor.


In normal message processing, only the handleMessage() method is called. The handleMessage() method is where the interceptor's message processing logic is placed.

If an error occurs in the handleMessage() method of the interceptor, or any subsequent interceptor in the interceptor chain, the handleFault() method is called. The handleFault() method is useful for cleaning up after an interceptor in the event of an error. It can also be used to alter the fault message.

The direction of a message can be determined by querying the message exchange. The message exchange stores the inbound message and the outbound message in separate properties.[1]

The message exchange associated with a message is retrieved using the message's getExchange() method. As shown in Example 4.1, getExchange() does not take any parameters and returns the message exchange as a org.apache.cxf.message.Exchange object.


The Exchange object has four methods, shown in Example 4.2, for getting the messages associated with an exchange. Each method will either return the message as a org.apache.cxf.Message object or it will return null if the message does not exist.


Example 4.3 shows code for determining if the current message is outbound. The method gets the message exchange and checks to see if the current message is the same as the exchange's outbound message. It also checks the current message against the exchanges outbound fault message to error messages on the outbound fault interceptor chain.




[1] It also stores inbound and outbound faults separately.

Example 5.1 shows configuration for attaching interceptors to a bus' inbound interceptor chain.


Example 5.2 shows configuration for attaching an interceptor to a JAX-WS service's outbound interceptor chain.


Interceptors can be attached to endpoints programmatically using either one of two approaches:

  • the InterceptorProvider API

  • Java annotations

Using the InterceptorProvider API allows the developer to attach interceptors to any of the runtime components that have interceptor chains, but it requires working with the underlying Fuse Services Framework classes. The Java annotations can only be added to service interfaces or service implementations, but they allow developers to stay within the JAX-WS API or the JAX-RS API.

Example 5.4 shows code for attaching an interceptor to the inbound interceptor chain of a JAX-WS consumer.

Example 5.4. Attaching an interceptor to a consumer programmatically

package com.fusesource.demo; 

import java.io.File; 
import java.net.URL; 
import javax.xml.namespace.QName; 
import javax.xml.ws.Service; 

import org.apache.cxf.endpoint.ClientProxy;
import org.apache.cxf.endpoint.ClientProxy;

public class Client 
{ 
  public static void main(String args[]) 
  { 
    QName serviceName = new QName("http://demo.eric.org", "stockQuoteReporter"); 
    Service s = Service.create(serviceName); 1

    QName portName = new QName("http://demo.eric.org", "stockQuoteReporterPort"); 
    s.addPort(portName, "http://schemas.xmlsoap.org/soap/", "http://localhost:9000/EricStockQuote"); 2
 
    quoteReporter proxy = s.getPort(portName, quoteReporter.class); 3

    Client cxfClient = ClientProxy.getClient(proxy); 4

    ValidateInterceptor validInterceptor = new ValidateInterceptor(); 5
    cxfClient.getInInterceptor().add(validInterceptor); 6

    ...
  } 
}

The code in Example 5.4 does the following:

1

Creates a JAX-WS Service object for the consumer.

2

Adds a port to the Service object that provides the consumer's target address.

3

Creates the proxy used to invoke methods on the service provider.

4

Gets the Fuse Services Framework Client object associated with the proxy.

5

Creates an instance of the interceptor.

6

Attaches the interceptor to the inbound interceptor chain.

Example 5.5 shows code for attaching an interceptor to a service provider's outbound interceptor chain.


The code in Example 5.5 does the following:

1

Creates a ServerFactoryBean object that will provide access to the underlying Fuse Services Framework objects.

2

Gets the Server object that Fuse Services Framework uses to represent the endpoint.

3

Gets the Fuse Services Framework EndpointImpl object for the service provider.

4

Creates an instance of the interceptor.

5

Attaches the interceptor to the endpoint;s outbound interceptor chain.

Example 5.6 shows code for attaching an interceptor to a bus' inbound interceptor chain.

Example 5.6. Attaching an interceptor to a bus

import org.apache.cxf.BusFactory;
org.apache.cxf.Bus;

...

Bus bus = BusFactory.getDefaultBus(); 1

WatchInterceptor watchInterceptor = new WatchInterceptor(); 2

bus..getInInterceptor().add(watchInterceptor); 3

...

The code in Example 5.6 does the following:

1

Gets the default bus for the runtime instance.

2

Creates an instance of the interceptor.

3

Attaches the interceptor to the inbound interceptor chain.

The WatchInterceptor will be attached to the inbound interceptor chain of all endpoints created by the runtime instance.

The InterceptorChain object has two methods, shown in Example 6.2, for adding interceptors to an interceptor chain. One allows you to add a single interceptor and the other allows you to add multiple interceptors.


Example 6.3 shows code for adding a single interceptor to a message's interceptor chain.


The code in Example 6.3 does the following:

1

Instantiates a copy of the interceptor to be added to the chain.

Important

The interceptor being added to the chain should be in either the same phase as the current interceptor or a latter phase than the current interceptor.

2

Gets the interceptor chain for the current message.

3

Adds the new interceptor to the chain.

The InterceptorChain object has one method, shown in Example 6.4, for removing an interceptor from an interceptor chain.


Example 6.5 shows code for removing an interceptor from a message's interceptor chain.


The code in Example 6.5 does the following:

1

Instantiates a copy of the interceptor to be removed from the chain.

Important

The interceptor being removed from the chain should be in either the same phase as the current interceptor or a latter phase than the current interceptor.

2

Gets the interceptor chain for the current message.

3

Removes the interceptor from the chain.

Table B.2 lists the interceptors added to a JAX-WS endpoint's inbound message chain.


Table B.3 lists the interceptors added to a JAX-WS endpoint's outbound message chain.


Table B.6 lists the interceptors added to a endpoint's inbound message chain when using the SOAP Binding.


Table B.7 lists the interceptors added to a endpoint's outbound message chain when using the SOAP Binding.


A

AbstractPhaseInterceptor, Abstract interceptor class
addAfter(), Add to the chain after
addBefore(), Add to the chain before
constructor, Setting the phase

C

configuration
inbound fault interceptors, Configuration elements, The annotations
inbound interceptors, Configuration elements, The annotations
outbound fault interceptors, Configuration elements, The annotations
outbound interceptors, Configuration elements, The annotations

H

handleFault(), Unwinding after an error
handleMessage(), Processing messages

I

inFaultInterceptors, Configuration elements
inInterceptors, Configuration elements
interceptor
definition, Interceptors
life-cycle, Chain life-cycle
Interceptor, Interfaces
interceptor chain
definition, Interceptor chains
life-cycle, Chain life-cycle
programmatic configuration, Adding interceptors programmatically
Spring configuration, Adding interceptors using configuration
InterceptorChain
add(), Adding interceptors
remove(), Removing interceptors

O

org.apache.cxf.Phase, Specifying a phase
outFaultInterceptors, Configuration elements
outInterceptors, Configuration elements

P

PhaseInterceptor, Interfaces
phases
definition, Phases
inbound, Inbound phases
outbound, Outbound phases
setting, Setting the phase