ColdFusion Migration to Java or .NET
Semantic Designs can provide your organization with highly accurate automated conversion of legacy ColdFusion applications (with embedded HTML, JavaScript and SQL) to modern technologies based on Java or C#.
Migrating ColdFusion to new languages such as Java or .Net promises the following nice properties:
- Makes the application more maintainable, and easier to enhance due to the enormous libraries available for Java and C#
- Enables some degree of automatic bug detection by virtue of (Java) compiler static analysis, which does not/cannot occur with ColdFusion so many such problems are found after deployment,
- Moves it to modern web technology such as JSP or Java Server Faces/PrimeFaces, enhancing developer productivity and users' UI experience
- Provides the organization with access to more easily found (Java) software engineers,
A key concern is, What will translated code look like? Weak translators convert code blindly line-by-line, with virtually no understanding of how the context of the code should shape its translation. Such translated code preserves the properties of the original ColdFusion, sometime the point of even preserving the syntax. Even if such code works, it not be maintainable and will ultimately cost the organization sorely.
Semantic Designs translators parse the original code with tools that have the same understanding as the original compilers; (for example, see our ColdFusion Front End). ColdFusion doesn't really provide declarations of variable types, so SD's tools need to infer appropriate Java/C# types based on how variables are used in the program, where and how they are used ("the context"). Using this information the translator can thus produce extremely good translations. Because SD also customizes the tools to the specific needs of the customer, the code reflects those needs properly.
A ColdFusion program translation
Here we show you a small sample of ColdFusion translated as SD's technology could translate it to Java.
A simple ColdFusion program
We have chosen to provide a small ColdFusion program to prevent the reader from being overwhelmed by the complexities that occur in real examples.
Each client has different goals and these can change the chosen target technology.
One should note that the translator must chose fixed data types
for variables compatible with their usage in the ColdFusion program or the database schema,
but with a different representation better suited for Java.
Note the different choice of Java integer types based
on the sizes of the values being stored.
In particular, note the choice of the Java BigDecimal class
used where ColdFusion values represent fractional or very big numbers.
The translation is adjusted to use appropriate method calls
on the BigDecimal class instead of
native Java operators +, -, *, /
which do not work on classes.
We remark that a different custom translation
could scale decimal numbers by 100 or 10000, allowing
use of Java-native + and - operators instead of method
calls. Which of these choices are made depend on what the client
thinks in more important to long term maintainablity:
representation of decimal numbers as 'decimals' in the BigDecimal
class with somewhat less readable expressions for decimal arithmetic,
or a slightly non-intuitive representation of decimal numbers with
readable expressions. Which combination of choices is made can determine very different style of translated code.
The translator needs to be configured to account for the client's choices.
For this example, we have chosen to use PrimeFaces.
Note that the translator produces a variety of files (java, xhtml)
that collectively implement the orginal Cold Fusion page.
The translator produces nicely formatted for each type of file as a standard by-product. One can get good code like the above, from a translator, if one has the right
foundation technology such as SD's DMS Software
Reengineering Tookit®. As a practical matter, you can't
get good code from an off the shelf translator,
because every application system has unique properties:
languages, OS features, scripting languages, screens,
databases, and a correspondingly unique set of target technologies as decided by the
client. It takes some effort to configure DMS for the client's
particular source and target software configurations.
The effort is rewarded by the maintainablity of the result.
Semantic Designs can provide custom configuration of migration tools and
migration
support to your organization, providing high quality, maintainable code translations.
<!--- DEMO.CF --->
<!--- DDL: CREATE TABLE Items ( PartID VARCHAR(17), Quantity INT, Cost DECIMAL(5,2) ) --->
<cfinclude template="definitions.cf">
<cif Country=="England"
<cfset CurrencySymbol="£">
<cfset Tax=.10>
<cfelse>
<cfset CurrencySymbol="$">
<cfset Tax=.05>
</cfif>
<cfquery datasource=#dsn# name="Items"
SQL="Select PartID,Quantity,Cost from ItemTable where Quantity>0"
</cfquery>
<table>
<cfoutput>
<tr><th>PartNumber</th><th>
Quantity</th><th>Unit Price</th></tr>
<cfloop>
<tr><td><a href="BuyOne.cfm?buy=#Items.PartID#">#Items.PartID#</a></td>
<td>#Items.Quantity#</td>
<td>#CurrencySymbol##Items.Cost*(1+Tax)#</td>
<tr>
</cfloop>
</table>
</cfoutput>
ColdFusion program translated to Java
------------------------------Demo.java----------------------------------------------------
// Java Bean
import java.math.BigDecimal;
@Named
@ViewScoped
public class DemoBean implements Serializable {
DemoBean() {
if (Definitions.Count.eq("England") {
this.CurrencySymbol="£";
this.Tax=.10;
} else {
this.CurrencySymbol="$";
this.Tax=.05;
}
}
private char CurrencySymbol;
public char getCurrentSymbol() {
return CurrencySymbol;
}
public setCurrencySymbol(char currencySymbol) {
this.CurrencySymbol = currencySymbol;
}
private float Tax;
public float getTax() {
return Tax;
}
public void setTax(Tax float) {
this.Tax = Tax
}
public string UnitPrice(Cost BigDecimal) {
return CurrencySymbol + Cost.Multiply(1+Tax);
}
}
------------------------------Demo.properties.vo.java-------------------------------------
// Value Object
package com.semanticdesigns.demo.properties.vo;
import java.math.BigDecimal;
public final class ItemsVO implements java.io.Serializable {
private String partID;
private int Quantity;
private BigDecimal Cost;
public ItemsVO() {}
public ItemsVO(String PartID, int Quantity, BigDecimal Cost) {
this.partID = PartID;
this.quantity = Quantity;
this.cost = Cost;
}
public String getPartID() {
return this.PartID;
}
public void setPartID(String PartID) {
this.PartID = PartID;
}
public int getQuantity() {
return this.Quantity;
}
public void setQuantity(int Quantity) {
this.Quantity = Quantity;
}
public BigDecimal getCost() {
return this.Cost;
}
public void setCost(BigDecimal Cost) {
this.Cost = Cost;
}
@Override
public String toString() {
return "ItemsVO [PartID=" + PartID +
", Quantity=" + Quantity +
", Cost=" + Cost +
"]";
}
}
------------------------------Demo.properties.dao.java------------------------------------
// Data Access Object
package com.semanticdesigns.demo.properties.dao;
import java.math.BigDecimal;
import com.semanticdesigns.demo.properties.util.PropertiesLogger;
import com.semanticdesigns.demo.properties.vo.ItemsVO;
@org.springframework.stereotype.Repository
public class ItemsDAO {
@javax.persistence.PersistenceContext(
unitName = "demoEntityManager"
)
private javax.persistence.EntityManager entityManager;
private static String createItems() {
return "SELECT PartID,\n" +
" Quantity,\n" +
" Cost,\n" +
"WHERE Items.Quantity>0\n";
}
@org.springframework.transaction.annotation.Transactional
public java.util.List<ItemsVO> getItems() {
PropertiesLogger.enter();
java.util.List<ItemsVO> result = java.util.Collections.emptyList();
try {
javax.persistence.Query query = entityManager.createNativeQuery(createItems());
java.util.List<Object[]> list = query.getResultList();
PropertiesLogger.debug("List size: " + list.size());
result = list.stream().map(obj ->
new ItemsVO( ( (String) obj[0] // PartID
, (int) obj[1] // Quantity
, (BigDecimal) obj[2] // Cost
)).collect(java.util.stream.Collectors.toList());
}
catch (java.lang.Exception ex) {
PropertiesLogger.error(".getItems throws exception.", ex);
throw new org.hibernate.QueryException(ex);
}
finally {
PropertiesLogger.exit();
}
return result;
}
}
------------------------------Demo.UI.xhmtl-----------------------------------------------
<!-- Primefaces component -->
<p:dataTable var="Items" value="#{dtBasicView.Items}">
<p:column headerText="PartID" onclick="BuyOne.html?buy=#{Items.Name}">
<h:outputText value="#{Items.Name}" />
</p:column>
<p:column headerText="# In Stock">
<h:outputText value="#{Items.Quantity}" />
</p:column>
<p:column headerText="Unit Price">
<h:outputText value="#{DemoBean.UnitPrice(Items.Cost)}" />
</p:column>
</p:dataTable>
------------------------------------------------------------------------------------------
Configuring a custom migration tool to match client needs
DMS, "Design Maintenance System" and Refactor++ are registered trademarks of Semantic Designs, Inc.
The SD logo and "Semantic Designs" are registered service marks of Semantic Designs, Inc.
Software Reengineering Toolkit, CloneDR, PARLANSE, JOVIAL2C, Thicket, Smart Differencer, CheckPointer are trademarks of Semantic Designs, Inc.
The OMG logo is a registered trademark of the Object Management Group, Inc. in the United States and other countries.
To view our Privacy Policy, click here
Comments or problems: [email protected]
Migration