Azure Hybrid Connections + Java = Connected Mobile Apps

Enterprise mobile apps probably need a connection to some kind of on-premises resource, such as a database or a web service.  SOAP and REST API services are common, as are databases such as SQL Server, Oracle, MySQL.  Java and .NET skills are very commonly available in enterprises.  Wouldn’t it be great if you could create a connection from a mobile app to an on-premises API or database without an exposed proxy and without poking holes in the firewall?  One that is insensitive to NAT’ing?  And if such a connection could be created using the talents of the people already on staff, nirvana!

 

Hybrid Connections

The benefits and requirements of Hybrid Connections are listed on this page:
https://azure.microsoft.com/en-us/documentation/articles/integration-hybrid-connection-overview/.

As you can see in the drawing, Azure Service Bus Relay is hidden under the covers of a Hybrid Connection.  One of the great features of SB Relay is that all connections are outgoing.  The SB infrastructure in Azure brokers the connection.

To assemble the solution depicted above, I did the following:

  • Create two Hybrid Connections in the Azure Portal on the BizTalk Services pages
  • Create a SQL Server VM, but leaving port 1433 closed to the Azure LB
  • Install the Hybrid Connection manager on the VM, configured to connect on 1433
  • Create a trivial web API app on my desktop and note the port used by IIS Express = 31106
  • Install the Hybrid Connection manager on my desktop, configured to connect on 31106
  • Note in the portal that both HC’s are connected.
  • Build and test Java web site (installed in Azure Web Site – nexus point of connections) code to exercise the connections.

Here’s my hybrid connection configuration:

HC Config

Here’s the code that exercises the connection to SQL Server.  Note that in the connection string, I use the Host Name.  The Hybrid Connection name is not relevant – they just happen to match in this case.  Port 1433 is implicit.

 package org.example;
 
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class HelloSQLServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        response.setContentType("text/html");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().println("<h1>Hello Servlet</h1>");
        response.getWriter().println("querying SQL Server<br>");
        
        /**
         * Invoke sql server @ azure
         */
        String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
        String url = "jdbc:sqlserver://golive-sql2014;DatabaseName=<mydb>";
        String username = "user";
        String password = "password";
        try {
            /* Load database driver */
            Class.forName(driver);
            /* Establish database connection */
            Connection con = DriverManager.getConnection(url, username, password);
            /* Run query */
            PreparedStatement stmt = con.prepareStatement("select count(*) from tbPerson");
            /* Get return result */
            ResultSet resultset = stmt.executeQuery();
            /* Loop through every row  */
            while (resultset.next()) {
                response.getWriter().println("Number of records in tbPerson = " + resultset.getInt(1) + "<br>");
            }
            /* Close result set */
            resultset.close();
            /* Close database connection */
            con.close();
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }
}

HelloSQL

And here’s the Azure Web Site code to exercise the web API on my desktop.  Note that again, the Host Name is in the URL.  With a URL reference to a service, the port must be specified, as usual.  The API code on my desktop is .NET, but that’s irrelevant.  It could be any stack that can surface a RESTful API.  I didn’t open any ports on my desktop, nor did I change my router configuration.

 package org.example;
 
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.HttpURLConnection;
import java.net.URL;

public class HelloOnPremServlet extends HttpServlet
{
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        response.setContentType("text/html");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getWriter().println("<h1>Hello Servlet</h1>");
        response.getWriter().println("Accessing on-prem service via HttpURLConnection <br>");
    
        try {
            URL url = new URL("https://golivex1:31106/api/values");
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            conn.setRequestMethod("GET");            
            
            InputStream stream = conn.getInputStream();
            
            byte[] data = new byte[1024];
            int offset = 0;
            int bytesRead = stream.read(data, offset, 80);
            while (bytesRead != -1) {
                offset += bytesRead;
                bytesRead = stream.read(data, offset, 80);
            }
            response.getWriter().println(new String(data));
            
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }
}

HelloOnPrem

Conclusion

In this blog post, I have demonstrated that using Java code in an Azure Web Site, secure connections can be made to resources that would otherwise be unavailable.  If I installed similar code (using any framework supported by Azure Web Sites, currently ASP.NET, Node.js, PHP, Python, ASP, Java) into an Azure Mobile Service, your mobile device apps could use the same Hybrid Connection capability to gain such access.

Cheers!