Sep 30, 2014

Create QR Code with ZXing library and ColdFusion

Using a combination of ColdFusion, ZXing, and JavaLoader you can create QR codes very easily.
<!---
Jermaine Gonzales
Simple QR creation with error correction using the ZXING library and javaloader.
ColdFusion 11
ZXING jar files: http://mvnrepository.com/artifact/com.google.zxing
JavaLoader: http://javaloader.riaforge.org/
The ZXING library used will be influenced by the ColdFusion library CF8 = ZXING core 2.3.0.
This was put together by following a few samples currently floating around, I was unable to find one that used the error correction however.
--->
<h1>Create QR Code</h1>
<cfoutput>
<form action="#cgi.script_name#" method="post">
<label for="bcData">Data String:</label>
<textarea id="bcData" name="bcData" rows="3" cols="80"><cfif isDefined("form.bcData")>#trim(form.bcData)#</cfif></textarea>
<br />
<label for="size">Size:</label>
<input type="text" id="size" name="size" <cfif isDefined("form.size")> value="#trim(form.size)#"</cfif> />
<br />
<label for="errorC">Error Correction:</label>
<select id="errorC" name="ErrorC" >
<option value="L" <cfif isDefined("form.errorC") AND form.errorC IS "L">selected="selected"</cfif>>L</option>
<option value="M" <cfif isDefined("form.errorC") AND form.errorC IS "M">selected="selected"</cfif>>M</option>
<option value="Q" <cfif isDefined("form.errorC") AND form.errorC IS "Q">selected="selected"</cfif>>Q</option>
<option value="H" <cfif isDefined("form.errorC") AND form.errorC IS "H">selected="selected"</cfif>>H</option>
</select>
<br />
<input type="submit" name="generateCode" value="Create QR Code" />
</form>
</cfoutput>

<cfscript>
if ( isDefined("form.bcData") AND len( trim(form.bcData) ) ) {
variables.paths = arrayNew(1);
variables.paths[1] = expandPath("\wwwroot\zxing\core-3.1.0.jar");
variables.paths[2] = expandPath("\wwwroot\zxing\javase-3.1.0.jar");
variables.loader = createObject("component", "wwwroot.javaloader.JavaLoader").init( paths );
variables.barCodeFormat = loader.create('com.google.zxing.BarcodeFormat');
variables.MatrixToImageWriter = loader.create('com.google.zxing.client.j2se.MatrixToImageWriter');
variables.EncodeHintType = loader.create('com.google.zxing.EncodeHintType');

//setup the error correction level for the QR code
variables.errorCorrectionLevel = loader.create('com.google.zxing.qrcode.decoder.ErrorCorrectionLevel');
//use a java hashtable for hints information
variables.javaHash = loader.create("java.util.Hashtable").init();

//determine error correction level and set

if ( isDefined("form.errorC") ) {
switch(form.errorC) {
case "L":
variables.javaHash.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
//writeOutput("Choose L");
break;
case "M":
variables.javaHash.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
//writeOutput("Choose M");
break;
case "Q":
variables.javaHash.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
//writeOutput("Choose Q");
break;
case "H":
variables.javaHash.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//writeOutput("Choose H");
break;
default:
variables.javaHash.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
//writeOutput("Choose Default");
break;
}
}

// set the generated code size
if ( isDefined("form.size") AND len(trim(form.size)) AND isNumeric(trim(form.size)) ){
variables.useSize = trim(form.size);
}
else {
variables.useSize = 200;
}

//load the QR Writer and create the QR Code
try {
variables.QRCodeWriter = loader.create('com.google.zxing.qrcode.QRCodeWriter').init();
variables.QRcode = variables.QRCodeWriter.encode( trim(form.bcData), variables.barCodeFormat.QR_CODE, variables.useSize, variables.useSize, variables.javaHash );
variables.imageQR = ImageNew( variables.MatrixToImageWriter.toBufferedImage( QRcode ) );

//create image and display the QR image
imageWrite(variables.imageQR, "images/genQR.jpg", 1);
writeOutput('<img src="images/genQR.jpg" />');
}
catch ( any e ) {
//if something happens an exception is thrown at the java level so ColdFusion will time out if it tries to use the cfcatch.message and cfcatch.detail. This probably could be handled better but for now this will work. writeOutput("There was an error creating the QR Code");
}

//examples to create a different barcodes
/*
//load the PDF417 Writer and create the PDF417 Code
try {
variables.PDF417CodeWriter = loader.create('com.google.zxing.pdf417.PDF417Writer').init();
variables.PDF417code = PDF417CodeWriter.encode( form.bcData, BarcodeFormat.PDF_417, variables.useSize, variables.useSize );
variables.imagePDF417 = ImageNew( variables.MatrixToImageWriter.toBufferedImage( PDF417code ) );

//create image and display the QR image
imageWrite(variables.imagePDF417, "images/genPDF417.jpg", 1);
writeOutput('<img src="images/genPDF417.jpg" />');
}
catch ( any e ) {
writeOutput("There was an error creating the PDF417 Code");
}
//Load the AZTEC write and create the AZTEC code
try {
variables.AZTECCodeWriter = loader.create('com.google.zxing.aztec.AztecWriter').init();
variables.AZTECcode = AZTECCodeWriter.encode( form.bcData, BarcodeFormat.AZTEC, variables.useSize, variables.useSize );
variables.imageAZTEC = ImageNew( variables.MatrixToImageWriter.toBufferedImage( AZTECcode ) );
//create image and display the AZTEC image
imageWrite(variables.imageAZTEC, "images/genAZTEC.jpg", 1);
writeOutput('<img src="images/genAZTEC.jpg" />');
}
catch ( any e ) {
writeOutput("There was an error creating the AZTEC Code");
}
*/

}

</cfscript>

Apr 3, 2014

Remove Duplicates In A List Without A Loop

I had worked on a past project ColdFusion project that required me to process large amounts of list data from a ColdFusion web service. Part of the process involved removing duplicates, which was using a cfloop to loop through the list. They had a limit to the amount they could process since this was a web service and taking too long to respond back to the calling server can cause some timeout issues.

I was able to increase the amount that could be processed and increase performance by not not using a loop at all.

    <cfscript>
        lstNumbers = "1513,5845,9548,6955,5214,7845,3256,4588,1259,3578,9589,1513,3256,8599,5411,5698,8526,4785";
        writeOutput("List Length: " & #listLen(lstNumbers)# & "<br />");
        arrNumbers = listToArray(lstNumbers);
        writeOutput("Array Length: " & arrayLen(arrNumbers) & "<br />");
     
        objHashSet = createObject("java", "java.util.HashSet");
        objHashSet.init(arrNumbers);
        arrCleanNumbers = objHashSet.toArray();
        writeOutput("Array Length No Duplicates: " & arrayLen(arrCleanNumbers) & "<br />");
        lstCleanNumbers = arrayToList(arrCleanNumbers);
        writeOutput("List Length No Duplicates: " & listLen(lstCleanNumbers));

    </cfscript>

I first created an array and then initiated the java HashSet object. I then converted my array to a java array, doing this will automatically remove the duplicates in the array. You can then create a list from this array. Simple, fast and no looping required.

Mar 19, 2014

Color Coding Status Bar in Microsoft SQL Server Management Studio

This is one of those things you learn about when you make a change on the wrong server, well at least that is how I learned about it and why I share it when someone else makes the same mistake.

You can change the color of the status bar in Microsoft SQL Server Management Studio for every connection you make to help identify the server you are on.

The first step is to launch the Connect To Server option.


Then click on the "Options >>" button.


Then check the "Use custom color" check box then the "Select" button to choose a color.
I usually use Green for Development, Blue for Test and Red for Production.

Hope this helps someone before they make a mistake on the wrong server, but sometimes we have to learn the hard way.

Mar 18, 2014

SQL and XML

I was trying to figure out an issue with the new project I took over, and found some ColdFusion code that was throwing some errors trying to parse XML that came from a Microsoft SQL Server stored procedure. 

The stored procedure was using the FOR XML RAW to output XML instead of the query output that is normally returned. I have not used this before so I am unaware of any limitations that may be involved. The error was being caused by the result set being truncated and failing the reading of the XML result.

Here is an example of the SQL I got from Microsoft TechNet

USE AdventureWorks2012 
GO 
SELECT Cust.CustomerID, OrderHeader.CustomerID, OrderHeader.SalesOrderID, OrderHeader.Status 
FROM Sales.Customer Cust 
INNER JOIN Sales.SalesOrderHeader OrderHeader ON Cust.CustomerID = OrderHeader.CustomerID 
FOR XML RAW

The results that were being returned was rather large but I am unsure why that would be an issue. I did read about some truncation but that was blamed on the SQL Server Management Studio and its limitations on the size of the result set it could return.

The error I was receiving was being generated by ColdFusion so the SQL Server Management Studio limitations should not apply. I did solve my issue by using the XML data type that is available in Microsoft SQL Server 2005.

USE AdventureWorks2012 
GO 
DECLARE @xmlResult XML;
SET @xmlResult = (
SELECT Cust.CustomerID, OrderHeader.CustomerID, OrderHeader.SalesOrderID, OrderHeader.Status 
FROM Sales.Customer Cust 
INNER JOIN Sales.SalesOrderHeader OrderHeader ON Cust.CustomerID = OrderHeader.CustomerID 
FOR XML RAW)

SELECT @xmlResult

I have not run the above query as I am using a different table but the idea is there. I understand I could probably do something else but my knowledge of SQL is limited to the basic stuff, this works for me so I am using it until I discover a better solution.

Starting Over

I have neglected this blog for so long, things that seemed important or interesting at the time change as we grow older.

The one constant is my job I am a ColdFusion Developer and have been for a long time. So I decided to turn this blog into a place to share some interesting things I figure out as a developer that can maybe help out someone else and to help me keep track of them.