Migrating Java applications to .Net

How to convert existing Java or Visual J++ applications to J# or C#

Two paths are available for migrating Java applications to .Net: upgrade them to Visual J# .Net or convert them to Visual C# .Net. Upgrading Java applications to J# is the quickest and easiest way to port Java applications to the .Net Framework. Java developers are instantly productive on Visual J# .Net because they are already familiar with the syntax and set of class libraries.

Java applications can convert to C# using the Microsoft Java Language Conversion Assistant (JLCA). Code that calls Java APIs can convert to comparable C# code that uses the .Net Framework. The JLCA converts 90 percent of JDK-level 1.1.4 calls and emits issues in code for the other 10 percent. Each issue is linked to a topic with guidelines for modifications needed to finish the conversion.

Though converting to C# is slower than upgrading to J#, it offers more opportunities because converted applications use native .Net Framework APIs.

Download the source code that accompanies this article from Resources.

Sample Visual J++ application

As a demonstration, we have developed a sample Visual J++ (VJ++) application named CustomerDemo to port to .Net. The CustomerDemo application is modeled after a typical Java business application and uses some Java SDK APIs as well as Microsoft Java packages. CustomerDemo employs standard Java Database Connectivity (JDBC) APIs to access the SQL server to retrieve customer data. This data then transforms into hierarchical and flat views using the Java Collections API. The views are constructed by employing Microsoft Windows Foundation Classes (WFC). The following CustomerDemo parts will be detailed:

  • User interface
  • Database access
  • Common Java APIs used

User interface

CustomerDemo is a Windows application that has a Windows Form, ViewCustomer, shown in Figure 1:

Figure 1. CustomerDemo application

ViewCustomer is a com.ms.wfc.ui.Form hosting a typical set of Windows controls such as Panel, TreeView, Splitter, Edit, and Labels. It shows customers in a left-pane, hierarchical view. Countries are shown at the first level and customers at the leaf level. Clicking on each customer retrieves the detailed record of that customer data. These details include Contact and Address, shown in respective edit controls in the right pane.

Commercial applications generally have resources like icons and bitmaps stored in resource files. So, we also have an icon resource embedded in ViewCustomer Form and stored in the associated resource file ViewCustomer.resource.

Database access

We have provided the SQLData class that retrieves customer data from the Northwind database (sample database that comes with MS SQL server). SQLData accesses the database server by employing standard JDBC APIs. It connects to the database using the following code:

dbCon_ = DriverManager.getConnection(conInfo_,"","");

Country and customer data is retrieved using the following code:

stmt = dbCon_.createStatement();
rs = stmt.executeQuery(sqlQuery);
while(rs.next()){
      String countryId = rs.getString("Country");
      String companyName = rs.getString("CompanyName");
      //Package data into a Hashtable
      ...
}

Common Java APIs used

The CustomerDemo application uses common Java classes from java.util and java.lang packages. For example, it uses java.util.Hashtable to store the relationship between customers and countries. The java.util.Hashtable key is country name, and values are customers stored in a java.util.Vector. We use java.util.Enumerator to iterate the country keys and then get the associated list of customers. The relevant code is below:

Enumeration countryEnum = htCountryCompanyMap.keys();
while(countryEnum.hasMoreElements()){
String countryId = (String)countryEnum.nextElement();
      Vector companyList = (Vector)htCountryCompanyMap.get(countryId);
      ...
}

The SQLData class uses the java.lang.String and java.lang.StringBuffer classes to manipulate SQL queries. java.lang.Exception handles exceptions.

Migration to the .Net Framework

As previously mentioned, two good approaches are available to migrate existing Java applications to .Net:

  • Upgrade to J#
  • Convert to C#

Each migration path generates a different result. Table 1 shows what happens to the composition of Java projects when they migrate to .Net.

Table 1. Migration path

Java technologyUpgrade to J#Upgrade to C#
Java languageJava languageC# language
AppletNot convertedWindows Form control
JavaBeanJavaBeanC# class
Abstract Windowing Toolkit (AWT) frameAWT frameWindows Form
WFC FormWFC FormWindows Form
Compiled libraryCompiled libraryNot converted
Resource fileResX fileResX file

Upgrade to J#

Visual J# .Net consists of a Java language compiler, JDK-level 1.1.4 class libraries, and a tool to upgrade compiled Java byte code to Microsoft Intermediate Language (MSIL), which is useful for upgrading libraries to a form that can be used from .Net applications. In addition to JDK-level 1.1.4 class libraries, like other .Net-compliant languages, J# has full access to the .Net Framework and includes designers for Windows Form and Web Form development. J# offers familiar Java language syntax to build applications and services on .Net. We will now upgrade the Visual J++ CustomerDemo application to J#. We cover the following upgrade steps:

  • Visual J# Upgrade Wizard
  • Upgraded J# code
  • Upgrade issues

Visual J# Upgrade Wizard

The Visual J# Upgrade Wizard is included in the Visual J# installation with Visual Studio .Net. The Visual J# Upgrade Wizard can be invoked by opening the VJ++ project file (.vjp) in Visual Studio. We open CustomerDemo.vjp in Visual Studio to start the Visual J# Upgrade Wizard. The Upgrade Wizard asks for the type of application we want to convert as shown in Figure 2:

Figure 2. Visual J# Upgrade Wizard

We choose Windows Application and continue. We get an upgraded J# application named CustomerDemo_Net.vsproj containing the upgraded project files.

As we see in this wizard, the migration path exists for Java applications developed using JDK-level 1.1.4 class libraries. Java applications developed using JDK-level 1.1.4 class libraries can first be made part of a temporary VJ++ project. Subsequently, we can start the Upgrade Wizard from the temporary VJ++ project file and select either Console Application or Class Library.

Java applications that use higher JDK versions can also use the Upgrade Wizard to migrate the greater part of the application (business logic, JDK-level 1.1.4 classes, and most of the JDK 1.2 java.util package) automatically. The remaining Java technology can be replaced with comparable .Net APIs. Java applications using Swing should be migrated manually to Windows Forms. By copying the event-handling code in Swing Forms to the relevant Windows event handlers, most of the code can be reused.

The Upgrade Wizard also produces an upgrade report, _UpgradeReport.htm, listing relevant information and any problematic migration issues.

Upgraded J# code

J# provides a set of independently developed class libraries in .Net that offer the functionality of most JDK-level 1.1.4 class libraries and many classes in the JDK 1.2 java.util package. Therefore, the java.sql, java.util, java.lang, and com.ms.wfc packages used in our Java application upgrade to the same names in J#. Consequently, upgraded J# project CustomerDemo_Net.vsproj contains SQLData.java and ViewCustomer.java, and they look exactly like the former Java code shown in the example code snippets above. The ViewCustomer.resource file automatically converts to ViewCustomer.resX, a .Net-compatible resource file. Now we just build the upgraded J# code, run it, and see the same output as in Figure 1.

Upgrade issues

The original VJ++ form derived from com.ms.wfc.ui.Form migrates to the corresponding com.ms.wfc.ui.Form in J#. This imposes a limitation with using Windows Forms Designer for the upgraded form in Visual Studio because Windows Forms Designer cannot design forms derived from com.ms.wfc.ui.Form. So, any change in the upgraded form's user interface layout must be done manually. Alternatively, a backward approach can also work for altering upgraded, but very complex, user interfaces to meet the new requirements. We can use original VJ++ application code and the VJ++ editor to alter a form's layout. The changed form can be upgraded separately and then included in the migrated application again.

Convert to C#

C# is a native .Net language designed specifically for developing new generation .Net applications. Java applications can be migrated to C# to take advantage of the .Net Framework. In this section, we examine the process of converting the VJ++ CustomerDemo application to C#. We cover the following topics in this section:

  • Java Language Conversion Assistant
  • Converted C# code
  • Conversion issues and manual steps

Java Language Conversion Assistant

Visual Studio provides the Java Language Conversion Assistant (JLCA) to convert Java applications to C#. We launch JLCA from the File->Convert menu in Visual Studio. We choose VJ++ 6.0 Project as the conversion option shown in Figure 3:

Figure 3. JLCA wizard

We then select CustomerDemo.vjp as the source VJ++ project to convert to C#. We also choose CustomerDemo.NET as the newly converted C# project's name. We then go through the JLCA wizard's remaining steps to complete the C# conversion. We get a converted C# project CustomerDemo.csproj at the end of the conversion.

We can also convert a set of Java classes by choosing the second option in Figure 3.

Converted C# code

JLCA converts the VJ++ project and gives us a converted CustomerDemo.csproj. The project's Java classes and other files like resources in the CustomerDemo application convert to:

Table 2. Class-level VJ++ to C# conversion

JavaC#
ViewCustomer.javaViewCustomer.cs
SQLData.javaSQLData.cs
ViewCustomer.resourcesViewCustomer.resX
 

New class introduced:

SupportClass.cs

The JDK and Microsoft packages and classes used in CustomerDemo convert to:

Table 3. API-level VJ++ to C# conversion

JavaC#
java.sqlSystem.Data.Oledb
java.utilSystem.Collections
com.ms.wfc.ui.FormsSystem.Windows.Forms

java.lang.String

java.lang.StringBuffer

java.lang.Exception

System.String

System.Text.StringBuilder

System.Exception

The application's main() method converts to Main():

[STAThread]
public static void  Main(System.String[] args){
      System.Windows.Forms.Application.Run(new ViewCustomer());
}

The converted code in the data access class SQLData.java now uses ADO.Net (ActiveX Data Objects) instead of JDBC. The connectToDB() method establishes connection to the database using System.Data.OleDb.OleDbConnection():

dbCon_  = new System.Data.OleDb.OleDbConnection(conString);
dbCon_.Open();

The code for getting the record from the database is converted and uses System.Data.OleDb.OleDbCommand in place of java.sql.Statement, and System.Data.OleDb.OleDbDataReader in place of java.sql.ResultSet. The OleDbDataReader is accessed with the [] operator to get data from a column, which is similar to any normal array access. JLCA also introduces a new SupportClass to provide wrapper methods for controlling database transactions, which can be removed if not required. The converted code is below:

System.Data.OleDb.OleDbCommand stmt = SupportClass.TransactionManager.manager.CreateStatement(dbCon_);
stmt.CommandText = sqlQuery;
System.Data.OleDb.OleDbDataReader rs = stmt.ExecuteReader();
while (rs.Read()){
System.String countryId = 
      System.Convert.ToString(rs[("Country")]);
Syste.String companyId = 
      System.Convert.ToString(rs[("CompanyName")]);
...
}

Interestingly, JLCA converts the original getCountryCompany() method to a property CountryCompany of the SQLData class in C#. CountryCompany property's code is shown below:

public virtual System.Collections.Hashtable CountryCompany{
      get{
            ...
      }
}

The code to iterate java.util.Hashtable converts to System.Collections.Hashtable. Hashtable is accessed with the [] operator now. However, the converted code for iterating Hashtable does have a problem that we will manually correct in the next section. The converted code for Hashtable is:

System.Collections.IEnumerator countryEnum = (System.Collections.IEnumerator) htCountryCompanyMap.Keys;
while (countryEnum.MoveNext())
{
      System.String countryId = (System.String) countryEnum.Current;
System.Collections.ArrayList companyList = (System.Collections.ArrayList) htCountryCompanyMap[countryId];
...
}

The ViewCustomer user interface easily converts to C#. ViewCustomer Form now derives from System.Windows.Forms. The controls like TreeView, Edit, Label, and TextBox contained in ViewCustomer automatically convert. Also note that the Windows Forms Designer in C# can open ViewCustomer Form and make changes unlike the upgraded form in J#.

Conversion issues and manual steps

JLCA automatically converts much of the Java code into C# code. However, it still leaves certain issues that must be manually resolved before the converted CustomerDemo.csproj project can be compiled and run in .Net. Figure 4 shows the conversion report produced by JLCA, listing all these issues:

Figure 4. C# conversion report. Click on thumbnail to view full-size image.

Let's go through these issues and see how we can resolve them.

The first set of issues is related to some manual changes required in database access. The conversion comment UPGRADE_TODO points out that JdbcOdbcDriver did not convert. The JDBC driver used in the original code is not necessary in ADO.Net. So, we remove the line of code that loads the JDBC driver.

The next conversion comment indicates that the Connection string should be in the ADO.Net format. So, we must change our Connection string to:

String conInfo_ = "Provider=SQLOLEDB;Data Source=(local);Initial Catalog=Northwind;User ID=sa;Password=;";

The next UPGRADE_TODO comment indicates that java.sql.Statement.close should be removed. So, we manually remove this line wherever it occurs in the SQLData class.

Automatic conversion uses the System.Collections.IEnumerator to iterate through a Hashtable. In fact, we find that trying to get System.Collections.IEnumerator from Hashtable.keys produces a runtime exception. So, we must manually correct the code to instead use System.Collections.IDictionaryEnumerator to iterate through Hashtable keys. Here is the changed code:

System.Collections.IDictionaryEnumerator dictEnum = 
            htCountryCompanyMap.GetEnumerator();
while (dictEnum.MoveNext()){
      System.String countryId = (System.String)dictEnum.Key;
System.Collections.ArrayList companyList = 
            (System.Collections.ArrayList)dictEnum.Value;
      ...
}

The next set of issues relates to manual changes required in the user interface code. If we try to compile the CustomerDemo project at this point, we get a compiler error. On investigating this error further, we find that com.ms.wfc.ui.FontSize is not available in .Net. We used FontSize for setting the font style of the customer path control (a com.ms.wfc.ui.Label control) in the ViewCustomer Form in VJ++. We correct this problem by opening the ViewCustomer Form in the Windows Forms Designer and set the new font explicitly to the required style.

The default font used in the Windows Form in C# was Microsoft Sans Serif, 8.25pt instead of MS Shell Dlg, 11char as in VJ++. This automatic font switch caused the text to go beyond the size of the label controls in the ViewCustomer Form, so we must manually increase the labels' size so the text appears properly.

Now, we are ready to compile the converted CustomerDemo application and run it without any hiccups to see the same output as in Figure 1.

The move to .Net

Migration tools are available that facilitate the conversion of Java applications to Visual J# and Visual C#. Each method has its advantages: upgrading to J# is the quickest and easiest option, providing instant benefit to the Java application. Converting to C# is a slower option, but delivers maximum flexibility for the converted application. The choice of whether to use J# or C# depends on two major factors: migration time and framework.

When a Java application is upgraded to J#, the language stays as Java, and calls to JDK-level 1.1.4 APIs are preserved. When the same application converts to C#, the language converts to C#, and Java API calls convert to native .Net Framework calls. The quality of this conversion is very high (often upwards of 90 percent), but some modifications are required after the JLCA finishes. C# conversion takes longer than J# conversion. Applications converted to C# might experience improved performance, scalability, security, and versioning on the .Net platform. Applications upgraded to J# continue to use Java data types and Java libraries, although you can add new functionality with the .Net Framework.

If you choose to move to .Net, all of .Net's benefits are immediately available to your migrated applications, enabling developers to add new capabilities to existing applications.

Nitin Nanda is the associate project manager in the R&D Centre of Quark, based in Chandigarh, India. He is responsible for the front office suite of components for a customer relationship management (CRM) product engineered in COM/MTS/C++. He has coauthored Professional Java Data and Beginning Java Databases, both from Wrox Press. He worked for Cadence Design Systems prior to joining Quark. Sunil Kumar is an associate team lead in the R&D Centre of Quark, based in Chandigarh, India. He is responsible for design and development of the various components in a CRM product engineered in VJ++/ASP/COM+/SQL Server. He developed generic ERP software at RAMCO Systems prior to joining Quark.

Learn more about this topic