Saturday, February 24, 2018

Service Discovery using Curator Framework

In an environment hosting large number of web applications employing the traditional architecture with web server farm in the DMZ, and web applications in the walled garden zone static routing of requests using Apache mod_proxy or similar variants require restarting of web servers which require careful planning for maintenance.  In addition large number of entries for static routing in configuration files is error prone.  A better alternate would be a mod_proxy replacement which doesn't require restart of web servers, and automatic discovery of availability of services with the capability to add new services, and withdraw existing services.

Discussed in this blog is a simple idea introducing a proxy between the web servers and the application servers to enable dynamic routing of requests from the web servers to the application servers which eliminates the need for restarting web servers.

Traditional Architecture

The traditional architecture with web server farm in DMZ, and application servers within walled garden zone provide a neat scalable architecture for high volume web services.  In the traditional approach web servers in DMZ are configured as proxy servers to application servers using web server specific modules/connectors: e.g. apache mod_proxy.so for Apache Web Server, Tomcat AJP connector for routing the requests to Tomcat server, and several variations of the same proxy concept.

Need for a Dynamic Proxy

Typically the proxy configuration is manual, and any change to the configuration requires a restart of the web server.  While the manual configuration of routing can be automated using a variety of techniques, the requirement of restarting web servers for the changes to be effective is a significant drawback in case of micro services with large number of applications with large volumes of requests, new services added, existing services withdrawn.  A desired solution would be a proxy module which can automatically pick up the changes in the environment, and the changes in the environment do not require web server restart for the changes to be effective.  One such solution is to use a repository service where services register themselves, and de-register when withdrawn, and the proxy search the repository for the availability and end point of services.  The repository could be a database, a network file system, a zookeeper or any other shared storage system.  Apache Curator Framework provides extensions for such a storage system to store and query services and their endpoints.  As such the dynamic proxy discussed herein is targeted towards using Apache Curator Framework.     

Apache Curator Framework

Apache Curator Framework is a high-level API that greatly simplifies using ZooKeeper adding many features that build on ZooKeeper.  In addition extensions for Service Discovery, and Service Discovery Server are provided.

Self Registration

A service hosted in a servlet container can make use of the servlet container's life cycle methods for publishing their availability after servlet context initialized, and unavailability within the servlet context destroyed method.  Within the servlet context initialized method using the servlet context hostname, and port bindings can be obtained and used to register the internal end point for self registration. With self registration of services, services can publish their end points and availability dynamically.

Service Discovery

Depending on how the services publish their end points these end points could be accessible either externally or internally or both.  Client would execute a query for the service end point, and the query would then send the request to the end point thus retrieved.

Issues with Accessing Services through Load Balancer

The published end points could be external server names/ip addresses or internal server names/ip addresses which the load balancer is unaware off until load balancer is reconfigured.  While applications within the walled garden zone may be able to access these services using the internal addresses, either(both) load balancer reconfiguration, and web server proxy reconfiguration is(are) mandatory to make these services available through the load balancer.  In addition publishing internal server names/ip addresses to to the external services is not desirable as it could potentially be a security threat or the internal server names could not be resolved by external clients or the ip addresses are not accessible.

Services Aware Dynamic Proxy

Routing requests from load balancer/web server proxy to a services aware proxy server would eliminate the need for reconfiguring the load balancer or web server proxy, and restarting web servers in case of web servers being used as proxies.  This dynamic proxy would be responsible for routing the services to actual service end points using the internal hostname/IP Address.  As the proxy can access the services using the internal ip addresses, proxying the requests through the load balancer, web server would enable accessing the services externally through the load balancer.

This proxy will be responsible for intercepting the request, route the request to a functional endpoint using service discovery.  Apache mod_proxy can be modified to dynamically route the requests or a new module using Apache HttpClient library can be created querying the service discovery server, and routing the requests dynamically, eliminating the need to restart the web server.  Code at use-netty-to-proxy-your-requests can be modified to create the dynamic proxy as suggested herein.

Summary

Discussing the need for a dynamic proxy proposed a dynamic proxy querying the service discovery server to dynamically route the requests which would simplify deployment of services. 

Friday, February 23, 2018

Spring Framework - Injecting Map for Session Facade


Introduction

Spring Framework - Injecting Map Examples provided a working example for Injecting Map in Spring Framework.  With an extensive background in J2EE applications, and recently working with spring framework my immediate reaction was to use the same concept for implementing Session Facade in a web application.

Discussed in this blog is a simple implementation of Session Facade using Spring Framework. 

Demonstration Interface, and Classes

An interface Greeter with a single method getGreeting() which would return greeting is defined.  EnglishGreeter implementing Greeter would return "Welcome", and SpanishGreeter implementing the same would return "Bienvenido".  

Session Facade in Non-J2EE Applications

Similar to J2EE Applications several classes implement a common interface defining the specific business implementation.  Acknowledging that there are several methods of facade implementation, a simple implementation using switch statement to get Greeter based on language is shown below:

public interface Greeter {
  public String getGreeting();
}

public class EnglishGreeter implements Greeter {

  @Override
  public String getGreeting() {
    return "Welcome";
  }
}

public class SpanishGreeter implements Greeter {

  @Override
  public String getGreeting() {
    return "Bienvenido";
  }
}

public Greeter getGreeter(Sting lang) {
  Greeter greeter;
  switch (lang) {
    case "English":
      greeter = new EnglishGreeter();
      break;
    case "Spanish":
      greeter = new SpanishGreeter();
      break;
    case default:
      break;
    }
    return greeter;
}


Session Facade in J2EE Applications

Session Facade is one of the most employed design patterns in J2EE applications.  In case of Enterprise Java Beans(EJB) the session facade is implemented using a common interface with several EJBs implementing the base interface and incorporating the business specific logic within the implementing EJBs.

Again acknowledging that several implementations of session facade are possible, a simple implementation using if statement is demonstrated below: 


@Local
public interface Greeter {
  public String getGreeting();

}

@Stateless(name = "englishGreeter", mappedName = "ejb/englishGreeter")
public class EnglishGreeter implements Greeter {

  @Override
  public String getGreeting() {
    return "Welcome";
  }
}

@Stateless(name = "englishGreeter", mappedName = "ejb/spanishGreeter")
public class SpanishGreeter implements Greeter {

  @Override
  public String getGreeting() {
    return "Bienvenido";
  }
}

A simple client consuming above EJBs would look something similar to the following code:

@Local
public class GreeterClient {

  @EJB(mappedName = "ejb/englishGreeter")
  private Greeter englishGreeter;

  @EJB(mappedName = "ejb/spanishGreeter")
  private Greeter spanishGreeter;

  private Map<String, Greeter> map;

  public GreeterClient() {
    map.put("english", englishGreeter);
    map.put("spanish", spanishGreeter);
  }

  public void getGreeting(String lang) {
    Greeter greeter = map.get(lang);
    return greeter.getGreeting();
  }
}

Spring Framework Session Facade Injecting Map


Using Spring framework the same classes with annotations are shown below:

@Component(value="english")
@Qualifier("greeters")
public class EnglishGreeter implements Greeter {

  @Override
  public String getGreeting() {
    return "Welcome";
  }
}

@Component(value="english")
@Qualifier("greeters")
public class SpanishGreeter implements Greeter {

  @Override
  public String getGreeting() {
    return "Bienvenido";
  }
}

@Component
public class GreeterMapper {
    private Map<String, Greeter> map;

    @Autowired
    @Qualifier("greeters")
    public void setMap (Map<String, Greeter> map) {
        this.map = map;
    }

    public Map<String, Greeter> getMap () {
        return map;
    }
}

Spring framework uses value of the component as key, and class name as the value using the GreeterMapper.  The @Qualifier attribute enables grouping of the classes based on the value of the @Qualifier attribute.  GreeterMapper can be obtained from the SpringContext as shown below: 


GreeterMapper bean = context.getBean(GreeterMapper.class);
  
where context is the SpringContext.  Contents of GreeterBean demonstrating the mapping are shown below:

{english=com.teletubbies.util.EnglishGreeter@123f1134, spanish=com.teletubbies.util.SpanishGreeter@7d68ef40}

Language specific greeter from the facade can be obtained from a simple lookup of the map using Map's get method:

Greeter greeter = bean.getMap().get(lang);

Summary

With the help of sample code demonstrated simple facade implementation in ejb applications, and non-ejb applications without spring framework.  Compared with non-spring framework implementations, the annotation @Qualifier within the spring framework simplifies session facade implementation by automating the mapping for session facade. 


Sunday, February 18, 2018

Apache Spark - Connecting to MSSQL Databases using JDBC and Dataset Operations

Following the instructions from Databricks Connecting to SQL Database developed a program in Scala to retrieve data from MSSQL Server.  In the process have to read some documentation and some research on Google to merge dataframes, extract required fields from the resulting RDDs which contained duplicate column names, and writing the results to a single file.  Following were some of the tasks that were executed to create a single file containing the required data.

Adding MS SQL Server JDBC to library dependencies in sbt file

Instructions as provided at Microsoft JDBC Driver For SQL Server was added to the sbt file.

Reading Data from SQL

Instructions for reading data from SQL worked as detailed, it was not clear where the display function was.  As a result could not use the function display as documented.

Table schema

Part of the table schema used in the application was:
 |-- LabNumFr: integer (nullable = false)
 |-- Analyte: string (nullable = false)
 |-- Result: double (nullable = true)

Pushdown Queries to Database Engine

For performance reasons pushdown queries to database engine were used.  Three distinct datasets each representing a different Analyte(Mg, P, and K) were created using three different pushdown queries.  Sample contents were:
+--------+-------+-------+
|LabNumFr|Analyte| Result|
+--------+-------+-------+
|   78304|     Mg|117.259|
|   78404|     Mg| 95.881|
|   78410|     Mg| 32.595|
|   78423|     Mg|338.594|
|   78426|     Mg| 14.832|
+--------+-------+-------+

Merging Datasets using Alias

Joining datasets for further analysis was required.  Noting that LabNumFr was the key for joining the results, the datasets were joined using the dataset join method.  Since the datasets have identical column names, dataset's alias had to be used to select the column.  The query was similar to:

val dfPMg = dfMg.alias("Mg").join(dfP.alias("P"), "LabNumFr").join(dfK.alias("K"), "LabNumFr")

Merging Datasets

A single dataset containing results of Mg, P, and K was obtained using select command on dataset as below:

dfPMg.select("Mg.Result", "P.Result", "K.Result")

Writing results to single file using coalesce

Finally the results were all written to a single file using coalesc command without which the data was written to several files.  The command was:
dfPMg.select("Mg.LabNumFr", "Mg.Result", "P.Result", "K.Result")
.rdd.cache()
.coalesce(1)
.saveAsTextFile("/tmp/results.csv")

Sunday, February 11, 2018

Using Jersey2Config to generate Swagger 2.0 definition files

Swagger Core Jersey 2.X Project Setup 1.5


Generating swagger.json using Swagger core required some patience.  Following the documentation at https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5#using-the-application-class using Servlet 3.1 finally was able to create swagger.json.  https://github.com/htotapally/Spring5.git is the link to source code.  web.xml contains the swagger initialization code, shown below:

<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">


<servlet>
<servlet-name>Jersey2Config</servlet-name>
<servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0.0</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>/tt/api</param-value>
</init-param>
<init-param>
<param-name>swagger.api.title</param-name>
<param-value>My Awesome API</param-value>
</init-param>

<load-on-startup>2</load-on-startup>
</servlet>

<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
            io.swagger.jaxrs.listing,com.sbt
        </param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>

</web-app>

Used the command: mvn clean install -Dp.type=war to generate the war file to be deploy in Tomcat.
Once deployed http://localhost:8080/tt/api/swagger.json provided the description of the Rest services provided in the EmployeeResource.  Finally used to Swagger plugin to Chrome to test the API.  All worked out as expected once the Swagger project was set up correctly