Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

A Common CXF Request Interceptor for All OSGi Bundles

DZone's Guide to

A Common CXF Request Interceptor for All OSGi Bundles

· Java Zone
Free Resource

Learn how to troubleshoot and diagnose some of the most common performance issues in Java today. Brought to you in partnership with AppDynamics.

I have been working on Apache CXF, Karaf, Felix from path few months and I find all these bundled technologies very interesting to work with. While working on some use cases i have been got into a situation where i need only One Interceptor that should be executed on each HTTP request sent to any of bundles deployed under application in Karaf.

Basically i want to Authorize every request, change some headers and to do some security checks whatever request has been sent to the system and most importantly i want to do it at a single class. I found many ways to add interceptor in every bundle but i want to do that at some centralized location/bundle so that all the requests can be handled from that bundle. It can simply reject any request after doing some authorization or pass it to relevant bundle(cxf does that internally).

While doing this i came to know that CXF always creating a separate BUS for every RestServer that is being initialized in bundle’s Blueprint. But to achieve my goal we have to register all the bundles on same bus and apply the interceptor to that bus. With that we can control all the requests flowing on the bus.

Common Interceptor

public class CommonInterceptor extends AbstractPhaseInterceptor {

	public CommonInterceptor() {
		super(Phase.PRE_PROTOCOL);
	}

	public void handleMessage(Message message) throws Fault {
		
                /**
		 * Here write whatever logic you want to implement on each HTTP call sent to your project.
		 * 
		 * This interceptor will be called on every request that is being recieved by container and then will be sent
		 * to the relevant bundle/class for handling.
		 */

		String url = ( String ) message.get( URL_KEY_ );
		String method = ( String ) message.get( Message.HTTP_REQUEST_METHOD );

		LOGGER.debug( "################### Authentication Interceptor Validating Request : " + url + "####################" );

		Map< String, List< String >> headers = Headers.getSetProtocolHeaders( message );
                
                if ( headers.containsKey( X_AUTH_TOKEN ) ) {
                     return;
                }else{
                     message.getInterceptorChain().abort();
                }
		
          }
}

Above is the common interceptor code where you can do anything with the request that is being sent to your server. In constructor i am assigning the Phase to which that interceptor will be hooked up. There are several Phases in CXF. You can get information about Phases link: Phases in CXF.

Extending AbstractFeature:

public class InterceptorManager extends AbstractFeature {

	private static final String COMMON_BUS_NAME = "javapitshop_bus";
	private static final Logger LOGGER = LoggerFactory.getLogger(InterceptorManager.class);
	private static final Interceptor< Message > COMMON_INTERCEPTOR = new CommonInterceptor();

	protected void initializeProvider(InterceptorProvider provider, Bus bus) {
		
		if ( COMMON_BUS_NAME.equals( bus.getId() ) ) {
			LOGGER.debug( " ############## Registering Common Interceptor on BUS ##############" );
			bus.getInInterceptors().add( COMMON_INTERCEPTOR );
		} else {
			LOGGER.error( " ############## Bus Id: '" + bus.getId() + "' doesn't matched with system bus id ##############" );
		}	
	}
}

In above code i am extending AbstractFeature class and hooking up initilizeProvider method. Then i have given a name to our common bus. Basically whenever any OSGi Bundle gets installed it registered itself with the bus. In that case we are checking if the bundle has the desired bus Id. That bus ID will be unique system wide and all the bundles having this bus id will be registered to same bus and each and every request that will be related to those bundles will be sent to CommonInterceptor first.

Bus Registration In Bundles:

<cxf:bus id="javapitshop_bus">
		<cxf:features>
			<cxf:logging />
		</cxf:features>
	</cxf:bus>

To register the bundles with same bus you have to give an Id to that bus and register it in bundle’s blueprint.xml file. Do this in all relevant bundles and all those bundles will be assigned the same bus and CommonInterceptor will automatically be implemented to all the bundles.

You can downlaod the complete source code from my Github.

Understand the needs and benefits around implementing the right monitoring solution for a growing containerized market. Brought to you in partnership with AppDynamics.

Topics:

Published at DZone with permission of Shan Arshad, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}