Path of a packet with OpenDaylight managing OpenFlow devices

What I have tried to stitch together in this post is how a packet flows between a OpenFlow enabled network device to the controller which processes it (& how or using which interfaces) and return back path of the packet.

You might have seen the standard OpenDaylight architecture as below already.

ODL_ArchitectureFirst, it is important to understand the above diagram briefly, to lay the expectations:

  1. OpenFlow Enabled Devices: This is the network infrastructure that is managed via OpenDaylight. In this case OpenFlow plug-in.
  2. Protocol Plugins: OpenDaylight supports these protocols for managing your network devices. One of the plugins is OpenFlow.
  3. Service Abstraction Layer (SAL): Magic! This layer does all the plumbing between the applications and the underlying plugins.
  4. Controller Platform: These are the applications that come pre-bundled with OpenDaylight to manage the network. (You can write your’s too!)
  5. Network Applications: These are applications with leverage REST NBI of OpenDaylight to build intelligence. Here is a sample Network Statistics SDN Application that I have done!

Now, below is how packet flow from network to OpenDaylight & back to network takes place:

ODL_Packet_Lifecycle

  1. A packet arriving at a network device will be sent to the appropriate protocol plugin of OpenDaylight which is managing the switch.
  2. IPluginOutDataPacketService: The plugin (in our case OpenFlow Plug-in) will parse the packet, generate an event for Service Abtraction Layer (SAL) for further processing.
  3. IListenDataPacket: SAL will dispatch the packet to all the modules listening for DataPacket. These could be existing OpenDaylight applications like ARP Handler of your applications.
  4. IDataPacketService: Application/Module does the processing on the packet as per the business logic built and sends a PACKET_OUT using IDataPacketService.
  5. IPluginInDataPacketService: SAL recieves the DataPacket and dispatches it to the modules listening for plug-in DataPackets. In this case OpenFlow plugin.
  6. OpenFlow plugin then sends the packet back to the switch from where the packet was originated.

This is as per my understanding & if you think I have missed something or you need more details and code samples, let me know.

Advertisements

What is Mininet? Simple explaination

Starting on to experiment or learn SDN concepts? So where do you start?

Baseline requirement to do/experiment anything in SDN is the need of network devices with OpenFlow. So, how do you go about it and how do you get it?

First way to go about it is buy real hardware from vendors who have OpenFlow enabled switches in market, which can be extremely expensive, time exhausting and bad way to experiment.

Second, you could get Mininet.

Mininet is a software emulator for prototyping a network on a single machine.

Simply put, this is all it takes:

  1. Run just one command (sudo mn) on Mininet, and you get,
  2. Network topology with hosts & devices, which is connected to
  3. A bundled SDN Controller

mininet

So, Mininet can be used to quickly create a realistic virtual network running actual kernel, switch and software application code on a personal computer.

Now, with Mininet in your hands, you can experiment with OpenFlow, play with the topology you want, learn concepts and also, build SDN applications easily.

Mininet proved to be a great kickstarter for me & opened up the space for me. There is already so much help available on Mininet but I’ll write as I find new or different things in it.

Network Statistics Sample SDN Application With OpenDaylight

I have been working on SDN applications for quite some time now and wanted to create a demo/sample app that could be reference or bootstrap app for people willing to explore more.

So I took some time out to come up with a idea of doing a very basic (some might call it no-brainer) SDN app for learning.

This application helps demonstrate following:
  • Demonstrate how REST API’s of a SDN Controller (in my case OpenDaylight) can be used to build a app.
  • I did not want to use any server-side programming/code to do this. This really shows the power of REST & SDN architecture.
  • Simple app that is easy to understand and replicate for someone learning this stuff.
  • Help you understand some concepts of SDN NBI that people talk about.
What is Network Statistics SDN Application ?

Bundled into a beautiful GUI, Network Statistics SDN Application runs on-top of a OpenDaylight SDN Controller and tracks port & table statistics of devices/nodes managed via OpenDaylight SDN Controller. Pure jQuery/Bootstrap and HTML based application without any server-side code.

Complete set of UI Screens developed for the application.

Things you can do in this application:

  1. Supply the URL/Username/Password of your OpenDaylight SDN Controller. Start tracking Nodes!
  2. View all the nodes managed by OpenDaylight in Network Devices section.
  3. View Port and Table statistics of each node found.

This is kind of no-brainier, but you can come up with more use cases around it etc, what this app if for? Its just for the kick-start.

If you are interested in running it:
  1. You can get the complete code from my git or if that’s too much work and you don’t intend to change code & just want to see it in action, download the file of this application from here (do “Save Link As“, this is .png, rename it to .war).
  2. Run the application either from code or by dropping the .war into tomcat/jetty/jboss (some web server)
  3. Supply your pre-installed OpenDaylight credentials and see it in action at http://localhost:8080/NetworkStatsApplication/
Assumptions:
  • I assume that you have a mininet and OpenDaylight setup working already as that is a per-requisite to building any application.
  • I prefer you read Brent’s blog on this which I refer whenever I’m stuck at things he has written about.

How I built this application and the code walk thru I have explained it in part-2 of this post as this blog was getting too long for everything.

Network Statistics Sample SDN Application With OpenDaylight Code Walk Thru

Continuing my earlier blog about the sample SDN application that I have created called Network Statistics SDN Application, here I’ll walk you thru the code and how I developed it.

Technologies used in this project are HTML, Twitter Bootstrap CSS, JQuery, JavaScript and WAR Packaging. This project is available at my git for download.

First, create a Java Dynamic Web Project. Here in this project although I do not use server-side code, but based on my confort in this tech-stack, that is what I chose.

18

 

 

 

 

 

 

 

 

Second, I searched online for some Bootstrap CSS based theme that would suffice this project & selected Freelancer Free Theme which I downloaded and copied into the WebContent of the above created project.

I have created the UI like this, with this theme.

Third, I changed the html file as per my needs and create four sections in it.

  1. Section 1: Place where I take input for SDN Controller releated credentials.
  2. Section 2: Place where we display Network Devices.
  3. Section 3: Place where we display selected device’s Port Statistics.
  4. Section 4: Place where we display selected device’s Table Statistics.

Hence, the complete HTML for above sections looks something like this:

<html lang="en">
<head>

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">

<title>Network Stats SDN Application | SDN{Geeks}</title>

<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/freelancer.css" rel="stylesheet">
<link href="font-awesome-4.1.0/css/font-awesome.min.css"
    rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=Montserrat:400,700"
    rel="stylesheet" type="text/css">
<link
    href="http://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic"
    rel="stylesheet" type="text/css">
</head>

<body id="page-top" class="index">

    <nav class="navbar navbar-default navbar-fixed-top">
        <div class="container">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header page-scroll">
                <button type="button" class="navbar-toggle" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1">
                    <span class="sr-only">Toggle navigation</span> <span
                        class="icon-bar"></span> <span class="icon-bar"></span> <span
                        class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#page-top">Network Stats SDN
                    Application</a>
            </div>

            <div class="collapse navbar-collapse"
                id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav navbar-right">
                    <li class="hidden"><a href="#page-top"></a></li>
                    <li class="page-scroll"><a href="#nodes">Network Devices</a></li>
                    <li class="page-scroll"><a href="#port">Port Stats</a></li>
                    <li class="page-scroll"><a href="#table">Table Stats</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <header>
        <div class="container">
            <div class="row">
                <div class="col-lg-10 col-lg-offset-1">
                    <p>
                        Network Statistics SDN Application runs on-top of a OpenDaylight
                        SDN Controller. <br />It tracks port, table and flow statistics
                        of all the nodes added to OpenDaylight. Run this application on
                        tomcat locally and supply the credentials below to see it in
                        action.
                    </p>
                    <p>This is a pure jQuery/Bootstrap and HTML based application
                        without any backend in itself.</p>
                </div>

                <div class="col-lg-12">
                    <br /> <br />
                    <div class="col-lg-3"></div>
                    <div class="col-lg-6">
                        <input type="text" class="form-control"
                            placeholder="SDN Controller URL" id="url"> <br /> <input
                            type="text" class="form-control"
                            placeholder="SDN Controller Username" id="username"> <br />
                        <input type="password" class="form-control"
                            placeholder="SDN Controller Password" id="password"> <br />
                        <br />
                        <div class="col-lg-8 col-lg-offset-2 text-center">
                            <a href="javascript:trackNetworkStatisticsClicked();"
                                class="btn btn-lg btn-outline"> <i class="fa fa-tachometer"></i>
                                Track Network Statistics
                            </a>
                        </div>

                    </div>
                    <div class="col-lg-3"></div>
                </div>
            </div>
        </div>
    </header>

    <section id="nodes">
        <div class="container">
            <div class="row">
                <div class="col-lg-12 text-center">
                    <h2>Network Devices</h2>
                    <hr />
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12" align="center">
                    <p>This section shows all the device loaded into OpenDaylight.
                        I have created a thumbnail for these devices.</p>
                    <p>You can very well use any JS plotting frameworks to show the
                        network topology also</p>
                    <br /> <br />

                </div>
            </div>

            <div class="row" id="nodesButton">
                <div class="col-md-12" align="center">
                    <a href="#page-top" class="btn btn-success"> Please enter
                        OpenDaylight credentials first. </a> <br /> <br />
                </div>
            </div>

            <div class="row hidden" id="nodesDiv">
            </div>
        </div>
    </section>

    <section id="port" style="background: #C8D1DA;">
        <div class="container">
            <div class="row">
                <div class="col-lg-12 text-center">
                    <h2>Port Statistics</h2>
                    <hr />
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12" align="center">
                    <p>This section shows the port statistics of the selected
                        device.</p>
                    <p>
                        You can intelligently show which ports are running maximum traffic
                        and are at risk etc. <br />There are numerous use cases that open
                        up with this data
                    </p>
                    <br /> <br />
                </div>
            </div>

            <div class="row" id="portButton">
                <div class="col-md-12" align="center">
                    <a href="#nodes" class="btn btn-success"> Please select a
                        device to view port statistics. </a> <br /> <br />
                </div>
            </div>

            <div class="row hidden" id="portDiv">
            </div>
        </div>
    </section>

    <section id="table">
        <div class="container">
            <div class="row">
                <div class="col-lg-12 text-center">
                    <h2>Table Statistics</h2>
                    <hr>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12" align="center">
                    <p>This section shows the OpenFlow table statistics of the
                        selected device.</p>
                    <p>This information is helpul in pre-configuring the switch and
                        knowing the switch capacity.</p>
                    <br /> <br />
                </div>
            </div>

            <div class="row" id="tableButton">
                <div class="col-md-12" align="center">
                    <a href="#nodes" class="btn btn-success"> Please select a
                        device to view table statistics. </a> <br /> <br />
                </div>
            </div>

            <div class="row hidden" id="tableDiv">
            </div>

        </div>
    </section>

    <footer class="text-center">
        <div class="footer-below">
            <div class="container">
                <div class="row">
                    <div class="col-lg-12">Network Statistics SDN Application by
                        Saurabh Agarwal</div>
                </div>
            </div>
        </div>
    </footer>

    <script src="js/jquery-1.11.0.js"></script>
    <script src="js/bootstrap.min.js"></script>
    <script
        src="http://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script>
    <script src="js/classie.js"></script>
    <script src="js/cbpAnimatedHeader.js"></script>
    <script src="js/jqBootstrapValidation.js"></script>
    <script src="js/contact_me.js"></script>
    <script src="js/freelancer.js"></script>
    
    <!-- This is where all the magic happen -->
    <script src="scripts/NetworkStats.js"></script>

</body>

</html>

Fourth, let’s move on to the javascript where the actual calls are made. I have created NetworkStats.js inside script folder and included in the above html.

<!-- This is where all the magic happen -->
<script src="scripts/NetworkStats.js"></script>

Fifth, for each action on the html page, I have written a corresponding javascript functions.

  1. Track Network Status” action – Here we take input from user for OpenDaylight credentials and fetch nodes via REST API.
  2. Port Stats” action – Here we take the node id and name of the device & fetch port statistics via REST API.
  3. Table Stats” action – Here we take the node id and name of the device & fetch port statistics via REST API.

Hence the complete javascript looks like this:

//Global Variables
var sdnControllerURL = null;
var sdnControllerUserName = null;
var sdnControllerPassword = null;
var base64EncodedPassword = null;

// Get the values supplied
// Store them in global valiables
// Populate Network Device section
// Show Network Devices
function trackNetworkStatisticsClicked() {

    sdnControllerURL = $("#url").val();
    sdnControllerUserName = $("#username").val();
    sdnControllerPassword = $("#password").val();
    base64EncodedPassword = "Basic "
            + btoa(sdnControllerUserName + ":" + sdnControllerPassword);

    console.log(sdnControllerURL);
    console.log(sdnControllerUserName);
    console.log(sdnControllerPassword);
    console.log(base64EncodedPassword);

    if (ifCredentialsNotNull(sdnControllerUserName, sdnControllerPassword)) {
        populateNetworkNodes();
    } else {
        alert("Trying error cases huhh..? Please enter createndials.");
    }
}

// Fetch network nodes from OpenDaylight
// Populate Network Device section
// Show Network Devices
function populateNetworkNodes() {
    var nodes = null;
    $
            .ajax({
                url : sdnControllerURL
                        + "/controller/nb/v2/switchmanager/default/nodes",
                type : "GET",
                async : false,
                contentType : "application/json",
                success : function(data, textStatus, jqXHR) {
                    console.log(data);
                    nodes = data;
                },
                error : function(jqXHR, textStatus, errorThrown) {
                    alert("Unable to fetch OpenDaylight Nodes.\nDid you supply the credentials correct?");
                },
                beforeSend : function(xhr) {
                    // Default Base64 Encoding for (admin/admin)
                    xhr
                            .setRequestHeader("Authorization",
                                    base64EncodedPassword);
                }
            });

    if (nodes != null && nodes != undefined) {
        // Construct divs
        $.each(nodes.nodeProperties, function(index, value) {
            var div = getNetworkDeviceDiv(value.properties.description.value,
                    value.node.id, value.properties.macAddress.value,
                    value.properties.timeStamp.value);
            $("#nodesDiv").append(div);
        });

        $("#nodesDiv").removeClass("hidden").addClass("visible");
        $("#nodesButton").removeClass("visible").addClass("hidden");

    }

}

// Method to create the network device div programatically
// No logic here, just plain factory generating divs on supplied inputs
function getNetworkDeviceDiv(name, id, mac, upTime) {
    var div = '<div class="col-sm-6 col-md-4"><div class="thumbnail"><br /> <br /> <img src="img/device.png"><div class="caption">';
    div += '<h4>' + name + '</h4>';
    div += '<ul class="list-group">';
    div += '<li class="list-group-item"><b>Id:</b> ' + id + '</li>';
    div += '<li class="list-group-item"><b>Name:</b> ' + name + '</li>';
    div += '<li class="list-group-item"><b>MAC:</b> ' + mac + '</li>';
    div += '<li class="list-group-item"><b>Connected Since:</b> ' + upTime
            + '</li>';
    div += '</ul><p>';
    div += '<a href="javascript:showSwitchPortStats(\''
            + name
            + '\',\''
            + id
            + '\')" class="btn btn-success" role="button">Port Stats</a> &nbsp;&nbsp;';
    div += '<a href="javascript:showSwitchTableStats(\'' + name + '\',\'' + id
            + '\')" class="btn btn-success" role="button">Table Stats</a>';
    div += '</p></div></div></div>';

    return div;
}

// Fetch ports for a node from OpenDaylight
// Populate ports stats section
function showSwitchPortStats(name, id) {
    var ports = null;
    $
            .ajax({
                url : sdnControllerURL
                        + "/controller/nb/v2/statistics/default/port/node/OF/"
                        + id,
                type : "GET",
                async : false,
                contentType : "application/json",
                success : function(data, textStatus, jqXHR) {
                    console.log(data);
                    ports = data;
                },
                error : function(jqXHR, textStatus, errorThrown) {
                    alert("Unable to fetch OpenDaylight Node Ports.\nDid you supply the credentials correct?");
                },
                beforeSend : function(xhr) {
                    // Default Base64 Encoding for (admin/admin)
                    xhr
                            .setRequestHeader("Authorization",
                                    base64EncodedPassword);
                }
            });

    if (ports != null && ports != undefined) {
        // Construct divs
        var finalDiv = '<div class="col-lg-12"><div class="panel panel-success"><div class="panel-heading"><h4>';
        finalDiv += name + ' : Port Statistics</h4>';
        finalDiv += '</div><div class="panel-body">';

        // For each port create a sub element in the final div
        $.each(ports.portStatistic, function(index, value) {
            var div = getPortsDiv(value.nodeConnector.id, value.receivePackets,
                    value.transmitPackets, value.receiveBytes,
                    value.transmitBytes, value.receiveDrops,
                    value.transmitDrops);
            finalDiv += div;
        });

        finalDiv += '</div></div></div>';
        $("#portDiv").append(finalDiv);
        $("#portDiv").removeClass("hidden").addClass("visible");
        $("#portButton").removeClass("visible").addClass("hidden");

    }

}

// Method to create the port stats div programatically
// No logic here, just plain factory generating divs on supplied inputs
function getPortsDiv(portId, receivePackets, transmitPackets, receiveBytes,
        transmitBytes, receiveDrops, transmitDrops) {
    var div = '<div class="col-sm-2 col-md-2"><div class="thumbnail"><img src="img/port.png" alt="..." height="60" width="60"><div class="caption">';
    div += '<p align="center">Port ' + portId + '</p></div>';
    div += 'Packet Rx: ' + receivePackets + '<br /> Packet Tx: '
            + transmitPackets + '<br />Byte Rx: ' + receiveBytes
            + '<br />Byte Tx: ' + transmitBytes + '<br />Drop Rx: '
            + receiveDrops + '<br />Drop Tx: ' + transmitDrops + '</div></div>';
    return div;
}

// Fetch table stats for a node from OpenDaylight
// Populate table stats section
function showSwitchTableStats(name, id) {
    var tableStats = null;
    $
            .ajax({
                url : sdnControllerURL
                        + "/controller/nb/v2/statistics/default/table/node/OF/"
                        + id,
                type : "GET",
                async : false,
                contentType : "application/json",
                success : function(data, textStatus, jqXHR) {
                    console.log(data);
                    tableStats = data;
                },
                error : function(jqXHR, textStatus, errorThrown) {
                    alert("Unable to fetch OpenDaylight Node Table Stats.\nDid you supply the credentials correct?");
                },
                beforeSend : function(xhr) {
                    // Default Base64 Encoding for (admin/admin)
                    xhr
                            .setRequestHeader("Authorization",
                                    base64EncodedPassword);
                }
            });

    if (tableStats != null && tableStats != undefined) {
        // Construct divs
        var firstTable = null;
        var finalDiv = '<div class="col-lg-12"><div class="panel panel-success"><div class="panel-heading">';
        finalDiv += '<h4>' + name + ' : Table Statistics</h4>';

        // I'm only considering one table for this demo project.
        // You can actually iterate thru them to have multiple as per OF spec
        $.each(tableStats.tableStatistic, function(index, value) {
            firstTable = value;
            return;
        });

        finalDiv += '</div><div class="panel-body"><p>Table Id: '
                + firstTable.nodeTable.id + '</p></div>';
        finalDiv += '<ul class="list-group">';
        finalDiv += '<li class="list-group-item"><span class="badge badge-success">'
                + firstTable.activeCount + '</span>Active Count</li>';
        finalDiv += '<li class="list-group-item"><span class="badge badge-success">'
                + firstTable.lookupCount + '</span>Lookup Count</li>';
        finalDiv += '<li class="list-group-item"><span class="badge badge-success">'
                + firstTable.matchedCount + '</span>Matched Count</li>';
        finalDiv += '<li class="list-group-item"><span class="badge badge-success">'
                + firstTable.maximumEntries
                + '</span>Maximum Supported Entries</li>';
        finalDiv += '</ul></div></div>';

        $("#tableDiv").append(finalDiv);
        $("#tableDiv").removeClass("hidden").addClass("visible");
        $("#tableButton").removeClass("visible").addClass("hidden");

    }

}

// Utility function to check not null user name password
function ifCredentialsNotNull(username, password) {
    if (username != null && password != null && username != ''
            && password != '') {
        return true;
    }
    return false;
}

Now, deploy this application into tomcat/jetty/jboss or any other web server of choice & you should see it running.

Sixth, you can verify the application, by enabling firebug or browser web developer tools to see if REST API calls are going thru, some sample calls as I get them are below.

6 11 8

 

Hope you are able to build and run the application by yourself using the above steps.

Let me know if you find any issues & i’ll try to help.

Swagger example with JAVA, Spring, Apache CXF and Jackson

As I try to build more and more SDN applications on top of OpenDaylight and other SDN Controllers, there was a common need to give REST NBI document to other users to consume the REST API’s of my newly built apps.

So the questions I was trying to solve were:

  • How to say to clients how to use a REST API? There’s no real standard or at least de-facto standard to expose a REST contract.
  • Write manual documentation or let some tool generate it for me.
  • My written-by-hand web service documentation isn’t ever going to be up-to-date.
  • I was more interested in writing the services THAN its documentation

Hence I started evaluating a common REST API documentation frameworks and finally Swagger stuck me.

So what is Swagger?

  • Swagger is a specification for documenting REST API. As an application developer, I write web services using your favorite framework.
  • Swagger scans my code and exposes the documentation on some URL.
  • Any client can consume this URL (which comes as XML or JSON documents) and learn how to use your REST web services.
  • Client now knows which HTTP methods to call on which URL, which input documents to send, which status code to expect, etc.
  • Swagger is a specification and supports a wide range of frameworks.

I have created a simple project to help everyone see how to use Swagger on top of Spring, Apache CXF & Jackson.

How To Guide

1. Project Setup:

Please see the visual of my project setup, source code of which is available at my git here.

swagger-setup

 

 

 

 

 

 

 

 

 

 

2. REST API

I have written a very simple REST API for this demo, which has annotations like below

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;

@Path("/user")
@Api(value = "/user", description = "User REST for Integration Testing")
public interface UserService {

    @GET
    @Path("/getUser/{username}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "Get user details", response = User.class)
    public User getUser(@PathParam("username") String username);

    @POST
    @Path("/saveUser")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation(value = "Save user details", response = User.class)
    public User getUser(User user);
}

Interesting thing to note here is the @Api & @ApiOperation tags, which is a swagger tag and helps Swagger scan the elements needed and create the documentation. I have used minimal options from Swagger.

3. Swagger Config

Now to make this all work, and let swagger know of the packages to scan, URL to publish etc, below configuration is needed.

    <!-- Swagger API listing resource -->
    <bean id="swaggerResourceJSON" 
        class="com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON" />

    <!-- Swagger writers -->
    <bean id="resourceWriter"
        class="com.wordnik.swagger.jaxrs.listing.ResourceListingProvider" />
    <bean id="apiWriter"
        class="com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider" />

    <jaxrs:server address="/sw" id="swagger">
        <jaxrs:serviceBeans>
            <ref bean="swaggerResourceJSON" />
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <ref bean="resourceWriter" />
            <ref bean="apiWriter" />
        </jaxrs:providers>
    </jaxrs:server>

    <bean id="swaggerConfig" class="com.wordnik.swagger.jaxrs.config.BeanConfig">
        <property name="resourcePackage" value="com.sau.swagger.intg" />
        <property name="version" value="2.0" />
        <property name="basePath" value="http://localhost:8080/SwaggerUI-Integration/rest" />
        <property name="title" value="Swagger UI Integration Sample" />
        <property name="description"
            value="Swagger UI Integration Sample for demonstrating its working." />
        <property name="contact" value="saurabh29july@gmail.com" />
        <property name="scan" value="true" />
    </bean>

4. Swagger GUI

Once above is done and you deploy the project on a web server (tomcat etc), access the URL (http://localhost:8080/SwaggerUI-Integration/nbiDocs/index.html) to see the interactive UI in action.

swagger-ui-3 swagger-ui-2

swagger-ui-1

If you need a skeleton project to get this working or for reference, please download the source from my git here.