This page outlines the process to employ the namespace migration of Sqoop from
org.apache.sqoop. The specific JIRA issues tracking this work are filed under SQOOP-369.
Note: The information provided here is general information. Any detail specific to a particular aspect of this migration should be noted in the relevant JIRA issue.
Migration of Sqoop source code from
org.apache.sqoop is a prerequisite for releasing Sqoop under Apache Incubator. Considering that there is a lot of third party code that is developed on top of/to work with Sqoop, this migration is particularly risky for backward compatibility and thus requires careful handling. This document outlines the steps that seem reasonable for such migration.
If you are helping out with this migration and feel that the steps outlined here are not valid in some scenarios, please initiate the discussion on the developer mailing list and help update this document.
When migrating a class from its previous namespace to the new, the key requirement to address is that any code written to the old class should still work at binary compatibility level. This also implies that such code should be able to recompile with the migrated code base without any modifications. In order to enable this, the general approach is as follows:
- Any old public/protected/default access level API should be preserved as is, but marked deprecated.
- Any logic that exists in this API should be migrated to the new namespace.
Note that API is not just method signatures but includes all aspects of implementation such as class hierarchies, type compatibility, static and non-static state etc. The following sections outline these steps as they apply to various API scenarios.
Simple Public Class
Consider the class:
To migrate such a class, do the following:
- Create a new class in the new namespace and move all the APIs there.
- Modify the old class to mark it deprecated and remove all APIs from there.
- Modify the old class to make sure that the constructors remain the same and delegate to the corresponding super constructors.
- When referencing the new class from the old class, please use the fully qualified class name.
Here is the outcome:
Simple Public Class with Static Constants
Consider the following class:
To migrate this, do the following:
- Migrate as per the directions of migrating Simple Public Class (above).
- Create the same constants in the new class.
- Reference the new class constants from the old class to preserve the static API.
Simple Utility Class
A utility class is a simple class that has a private constructor and all methods as statics. Here is an example:
To migrate this class, do the following:
- Create a static class with the same API and implementation in the new namespace.
- Update the old class so that it delegates all invocations to the new class.
Here is how it will look like:
Concrete singletons are classes with static state that is bound to concrete implementation. Consider the class below:
In such cases you can only partially migrate it the class to the new namespace. Specifically, the non-static part can be migrated using inheritance but the static/singleton aspect will remain in the old class. The steps involved are the following:
- Migrate the non-static logic to a new base class in the new namespace.
- Retain the singleton logic in the old class.
The outcome will be something like the following:
Migrating Class Hierarchies
When migrating class hierarchies, you must create a parallel class-hierarchy in the new namespace using every migrated class. However, the important aspect of this migration is that in order to preserve the type-compatibility, you will have to have the new namespace classes inherit from their old super classes. Consider the following two class hierarchy:
To migrate this over to new namespace do the following:
- Start with the lowest level class and create its equivalent in the new namespace.
- The class thus created in the new namespace should inherit from the old class's super class.
- Repeat this process for every ancestor class in the hierarchy.
The outcome for the above example will be as follows:
Doing this will ensure that the type compatibility is preserved for all instances of the old classes with respect to their type hierarchies.