# BonCode - Full Content > Stories, Musings, Code Maintained by Bilal Soylu. Open-source, privacy-focused software. ## Welcome to BonCode Project Hub URL: https://www.boncode.net/ This platform serves as the central repository for my open-source initiatives, free, and experimental software. After the unexpected shutdown of a previous host, I’ve consolidated my work here to ensure long-term accessibility and streamlined indexing for the developer community. Transparency & Privacy First I believe in a cleaner, more ethical web. That’s why my projects are built with a privacy-centric philosophy: Zero Trackers: No analytics or data harvesting. Ad-Free Experience: No intrusive advertisements. Open Source or free: Most projects have their full source code published on GitHub for audit and collaboration. Explore and Download Whether you are a developer looking for inspiration or a user seeking privacy-focused tools, I invite you to explore my portfolio. Source Code: Accessible via my GitHub profile. Direct Downloads: Most software will work without installation. Use the navigation links at the below or the sidebar to find the latest builds and hosted software. Follow links to projects there ===> World Journey - Privacy Centric Travel Slideshow World Journey is a local-first privacy focused Progressive Web App (PWA) that transforms your travel photos with GPS metadata into cinematic 3D globe slideshow videos. You can export videos and share with family or any platform. Create stunning "travel journey" videos with automatic fly-to animations, all processed entirely in your browser with very limited backend dependency. You can run it completely locally if you don't need mapping. Bango - Automate Systematic Literature Reviews Bango automates the slowest part of any systematic review. Import your RIS or BibTeX file, set your inclusion and exclusion criteria, and let AI evaluate every abstract against your rules. You get a rigorously categorized set of articles with reasoning, tags, and confidence scores. ShortSizzle - Create Virtual Videos from Audio for Social Media ShortSizzle takes your audio recordings and written transcripts and turns them into short vertical videos - the kind that perform great on YouTube Shorts, TikTok, and Instagram Reels. Everything happens right in your browser. Nothing is uploaded to any server. German A1 - Vocabulary Training If you are learning German, the German A1 Coach is a learning tool that walks user in a structured manner through all the nouns and verbs of the A1 training as provided by the Goethe Institut. It uses an easy to understand chat interface. You can install as PWA on mobile devices and practice anywhere or use it on the web. Spanish A1 - Vocabulary Training If you are learning Spanish, the Spanish A1 Coach is a learning tool that walks user in a structured manner through all the nouns and verbs of the A1 training. It is similar to the German one but uses reviews specific problems areas that are typical for Spanish learners. It uses an easy to understand chat interface. You can install as PWA on mobile devices and practice anywhere or use it on the web. Big Timer Big Timer is a high-visibility, distraction-free Progressive Web App designed for public speakers, presenters, and performers. It prioritizes legibility from a distance and uses visual haptic alerts (screen flashing) to notify the speaker of remaining time without requiring them to read small numbers or hear an alarm. Coach Chat (Retired Project) I was playing with AI and seeing how that can be used in different ways. This was an experiment for people to play with but I discontinued it to reduce the charges that come with using hosted AI. Coach Chat AI It answers football questions but the model is not connected to latest football data so it can't give you any prediction for current season or games ;o) It also works with certain processing limits. So, if we run out of processing tokens for the month, you will only see errors. Simply, come back later and try again. You can ask the AI Coach to design training programs or get general football coaching tips. For example, "Design one hour optimized training program for my quarterback to improve passing accuracy." Use it with your Phantasy Football leagues or any other context or general football question you may have. Remember to have fun. Other Info This site is regularly updated even if the post date is not changed. You are free to use all open source projects within the given licenses as you wish and need. --- ## What is a BonCode URL: https://www.boncode.net/sample-page-2 BonCode what is it? The short answer to this question is, it is my handle. And, yes, I tried to be clever. I find, being clever many times to be an exercise in futility. But for some reason this stuck. I would guess it happened mainly because I developed code with that handle in it. And, being fundamentally lazy did not want to change it. Here is the initial thought behind it. If you have a little french understanding you already know that "bon" is something indicating  good. Code was meant to be straightforward reference to code, whether it is in conversation or programming, or a real world puzzle. So a handle composed of two-words meaning "good code", you say? "Yes" But, not so fast. You can also do another take on the word by breaking it apart differently, like so: "B", "on", and "Code". So, really three(ish) words. To add a little more nuance, B is my first initial of my first name "Bilal" and the remainder is literal english. So if used in the in English context it would be B on Code, meaning my opinions on development and other puzzles in the world. I was so enamoured by this sheer cleverness, that I never got around to getting a Twitter handler or .com domain (major face-palm). However, there you have it. BonCode it is. -Bilal   --- ## About BonCode URL: https://www.boncode.net/about-boncode This site is created and maintained by Bilal Soylu. BonCode is a handle I used for a while. Here is the explanation how I came up with it. This site was created in response to the demise of riaforge.org which used to host a lot of my open source code. I learned only after it went offline that it had gone so I don't even have backups of some the projects (sadness filled look ;o( ). Yes, I know, the first rule of computing, save, save, save... alas the projects that are still actively maintained are linked here and you can download. Most source code is available on GitHub and I hope this will be more secure in the long run. Simplified Legal Stuff: You are free to use any samples and code; all samples, unless otherwise noted, are published under Apache v.2  licenses. In short, you are totally and utterly at your own risk and merit if you use any code provided, though my heart goes out to you if you should run into issues. Obviously all content are my own totally unqualified opinions. Enjoy. --- ## BonCode Connector URL: https://www.boncode.net/boncode-connector Download Please use the latest download link for the connector: Latest Release on Github Online documentation is also updated regularly. Previous releases are available from GitHub as well. What is the BonCode Connector: The BonCode AJP (Apache JServ Protocol version 1.3) Connector uses already existing pathways to connect to Apache Tomcat (or any compliant servlet engine). It is the easiest to script and deploy AJP connector in our opinion. If you need to deploy a connector with IIS in a scripted fashion, the BonCode connector will save you weeks of programming time. The AJPv13 protocol details can be found here (http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html). In general it is a preference question whether you use the ISAPI connection, which is the old C/C++ way of connecting IIS to other protocols or the methods implemented in the BonCode connector. There are several advantages with the BonCode connector though: no ISAPI code (less risk of memory leaks, easier debugging) no IIS6 vestiges or backward compatibility elements needed on IIS7+ all managed code .net extensibility framework works on IIS5.1, IIS6, IIS7, IIS7.5, IIS8, IIS8.5, IIS9, IIS10 speed and stability improvements easier control by using IIS UI and handler mappings no virtual directories and virtual mapping needed configuration can be inherited to sub-sites and virtual sites easy install/uninstall support partial stream sending to browser (automatic flushing) with faster response to client support both 32/64 bit of Windows with same process and files transfer of all request headers to servlet container automatically forward to static error pages when Tomcat is not available built in simple-security for web-administration pages built in advanced security for CFML engines like lucee Documentation: Documentation is available as PDF in download package or online documentation. Quick Docs: How to connect Apache Tomcat to Microsoft IIS via AJP13 protocol and BonCode connector. Code & Support: All code is on GitHub if you like to expand, change, fix etc. Use the GitHub issues to report issues for follow up.       --- ## How to connect Apache Tomcat to IIS using AJP13 connector URL: https://www.boncode.net/boncode-connector/how-to-connect-apache-tomcat-to-iis-using-ajp13-connector If you are here, you are curious and have a need to connect JVM servlet driven infrastructure components running on Windows Operating System to IIS. Your servlet container could be anything like Tomcat, JBoss, Jira, etc., but for the remainder of this post we will assume the use of Apache Tomcat. We will also assume you don't want to get a new degree in computer science, changing configuration files, mucking with virtual directories and different bit versions of distribution files. IIS and Tomcat don't talk, meaning these technologies don't normally talk to each other in-process via native calls. They are separate processes operating independently. Thus, we will have to use an out-of-process connection between these two technologies in form of a protocol. We will use AJP version 1.3. There are a other protocols and ways to connect them, however, for our purposes we will focus on this: We will use the BonCode connector. Please download it from the main connector page. The BonCode connector works in-process with IIS and adds AJP 1.3 protocol support to IIS so that we can pass web request with high fidelity to Tomcat for processing and return responses correctly to callers. The installation of this connector is by far the simplest methodology currently available. After you have installed Tomcat and IIS. It boils down to three steps: a) Download distribution package b) unblock distribution package c) run installer and answer questions a) Download distribution package Please go to link above and click on the current downloadable version. b) unblock distribution package and unzip After you have downloaded the installation package you will need to make sure that you can execute the installation correctly. To avoid multiple issues with using the zip file content I would recommend that you unblock the zip package before unzipping. This avoids security issues with Windows Vista and later operating systems as well as Windows 2008 and later server operating systems. Simply right click on the zip file and click “Unblock” on the “General” tab.   c) run installer and answer questions Double click on the Connector_Setup.exe to start the installer. Accepting the installer defaults should get your system up and running. This will assume that all your IIS sites are connected to Tomcat. If not, change the answers where appropriate and select the sites to be connected.   More background information is available. There are more options and elements that you can choose from, but this is all you need to get going. To learn more visit the online manual.   Youtube Videos For those who rather watch the whole process here are some videos that walk through a few scenarios Install Tomcat 8 on Windows 2012 Server and use IIS 8 as frontend https://www.youtube.com/watch?v=JIUAeZc4Wfs How to connect Tomcat 7 and IIS7 https://www.youtube.com/watch?v=yVKiNAkhav8 JBOSS WildFly 9 on Windows 10 using IIS https://www.youtube.com/watch?v=ljeDnSV1bb0 Tomcat 7 and IIS7 using BonCode Connector with Wildcards https://www.youtube.com/watch?v=y6iwPEaLBY0 --- ## Upgrading Railo or Lucee connector URL: https://www.boncode.net/boncode-connector/upgrading-railo-or-lucee-connector The BonCode connector is bundled with the Railo and Lucee CFML engines. If you need to upgrade the connector you can follow the instructions here so-long as you used the Railo/Lucee installer for the initial install. First make a backup of the connector settings and install files. They are located in c:\windows\BonCodeAJP13.settings and [Railo/Lucee install]\AJP13 . The actual upgrade involves removing the existing connector and then installing the new version. a) MAKE A BACKUP: c:\windows\BonCodeAJP13.settings and [Railo/Lucee install]\AJP13 . b) Uninstall the existing connector: Run the Uninstallation program accessible in your control panel (Program and Features). Keep IIS features when prompted. c) Download new version package (zip file) from distribution point (http://www.boncode.net/boncode-connector) d) Unblock zip file: (http://boncode.net/connector/webdocs/Tomcat_Connector.htm#_Toc520189772) the downloaded .zip and, then, extract files. e) Copy the extracted files OVER the existing files in your Railo/Lucee install (e.g. [install]\AJP13 where [install] is the directory you have installed Railo\Lucee. f) Run the connector_setup.exe program and acknowledge the warning that "ALL YOUR INPUTS WILL BE IGNORED." If you do not see this warning do not proceed. You have not completed steps a-e correctly. g) from your initial backup in step a) copy your original setting file back from backup overriding the one located here c:\windows\BonCodeAJP13.settings h) Stop/Start IIS. That's it. --- ## Using BonCode with Adobe Coldfusion URL: https://www.boncode.net/boncode-connector/using-boncode-with-adobe-coldfusion Beginning with ColdFusion 10 Adobe moved away from JRUN and released ColdFusion on Tomcat servlet container. As part of this change they also built their connection mechanism on top of the original ISAPI connector for IIS. This is the connector that BonCode replaces in many circumstances. However, Adobe made modifications to both the Tomcat server code and the ISAPI connector code to accommodate their particular needs. Which brings up the question whether BonCode would work with the Adobe introduced changes. The upside of this is things for CF developers on IIS continue to mostly work like they have in the previous iterations, with maybe the only exception being, that you can no longer use CFFLUSH with the out of the box setup. You actually have to disable connector buffering (this has other side effects that you maybe OK with maybe not). To do so go to {CF-Home}/config/wscoonfig/{connector-no}/isapi_redirect.properties. Change iis_buffer_enable to false and restart the IIS. By now you also know that Adobe does not recommend you use the default Tomcat instance to host anything else besides ColdFusion. A good blog post: "What’s the deal with Tomcat in ColdFusion 10?"  by Rupesh Kumar explains this in more detail. On the other side, if you want to easily use one IIS to front-end multiple tomcat instances or applications, you really have to do something about the non-standard connector that ships with CF10-CF2018. Your IIS goes otherwise completely monkey-crazy if you try to work with the Adobe supplied one. The good news is that  that the BonCode connector has supported Adobe specific behavior in the transmission process since version 1.0.2 and CF10. Install CF The first step is actually to install CF as usual. Once the server install of CF is complete, however, you will need to remove the existing connector via the webserver config tool like so: Install BonCode Connector Once the removal of the Adobe connector is done, you can download the BonCode connector from GitHub connector and start the standard install. Accept all the defaults but once you get to the Tomcat information page, you will need to change the port based on your version of Adobe CF to: ColdFusion 10: CF10 uses AJP port 8012. ColdFusion 11: CF11 uses AJP port 8014 ColdFusion 2016: CF2016 uses AJP port 8016 ColdFusion 2018: CF2018 uses AJP port 8018 If your version is not mentioned, it probably uses a different port altogether. You can look at your worker.properties files to see which ports are used in the Adobe supplied connector and make the adjustments. Below is an example of the change needed for CF10. Adjust as needed for your version: Enable Adobe Mode: Adobe uses a different communication pattern that is not compatible with regular AJP protocol. You will need to let the connector know about it. You do so after the install is completed by making a modification to the BonCodeAJP13.settings file. This is located normally in the BIN directory in your site document root or in the C:\Windows directory for global installs. Add the following directive: <EnableAdobeMode>True</EnableAdobeMode> You need to restart IIS after this change. That should be it for basic operations. Securing The Connector (thanks to John Dickinson for this passage) Securing BonCode's connection with ColdFusion: Starting with ColdFusion 2018 Update 8 and ColdFusion 2016 Update 14, ColdFusion expects a secret phrase with each request for added security. ColdFusion requests return security errors until you tell BonCode about ColdFusion's secret phrase. Do this after the connector install is completed by modifying the BonCodeAJP13.settings file. This is located normally in the BIN directory in your site document root or in the C:\Windows directory for global installs. First, find the secret phrase in ColdFusion's Tomcat server.xml file located at the {cf.instance.home}\runtime\conf directory. Look for the connector line with protocol="AJP/1.3" in that file and copy just the secret phrase inside the secret attribute that looks something like this: secret="90A2DE1B-ABX8-5530-B095-B2AE7F7F5297" Add the following directive to the BonCodeAJP13.settings file, specifying the secret phrase you just copied, such as: <RequestSecret>90A2DE1B-ABX8-5530-B095-B2AE7F7F5297</RequestSecret> You need to restart IIS after this change. You may encounter an issue with slow response times after these changes. This is due to Tomcat resolution timeouts. Adding an address directive to your Tomcat server.xml AJP definition should solve this. Do not use localhost or 127.0.0.1. address="::1" Tweak the Connector For advanced operations you will need to add wildcard support for certain paths that Adobe CF uses If you want to take this a little further  I would suggest a few tweaks: a) If you want CFFLUSH support, check the appropriate option during the install of the connector on the options page.This is truly implemented as HTTP flush detection, rather than disabling of buffers and will not cause extra client or network overhead. b) Special Server Paths: If you want to explore the full functionality of CF I would also recommend that you add the wildcard mappings to the appropriate sub-folders in your CF site. This is used for some of its flex and background features: /CFFormGateway /flex2gateway /CFFileServlet /cfform-internal /flashservices/gateway /flex-internal /rest /pms /connector The directions on how to add wilcard mappings are also in the manual that is included in the download package for the BonCode connector. You should also disable remote access to some to these using standard IIS access restrictions: /pms /connector That is it for now. Please contact me via GitHub issues if there are changes that you wish to share. --- ## Bilal’s Blog Posts URL: https://www.boncode.net/bilals-blog-posts So, Yeah, I really do not keep any blog posts on this site or plattform. Please visit my blog at blogspot for now. I have been slacking lately, but you'll see for yourself. http://boncode.blogspot.com --- ## BonCode PGP for CFML URL: https://www.boncode.net/boncode-pgp-for-cfml BonCode PGP  This is the implementation of PGP as a library that can be plugged in to CFML Engines such as Adobe ColdFusion, Railo, Lucee, and OBD. Download Github: https://github.com/Bilal-S/cfpgp/releases Code Github: https://github.com/Bilal-S/cfpgp Support & Issues https://github.com/Bilal-S/cfpgp/issues --- ## Serverless Offline Plugin URL: https://www.boncode.net/serverless-offline-plugin About Serverless offline plugin allows you develop with the Serverless framework locally on your computer. Download https://github.com/dherault/serverless-offline Support https://github.com/dherault/serverless-offline/issues --- ## WDDX.net Library for .net URL: https://www.boncode.net/wddx-net-library-for-net Download https://github.com/Bilal-S/WDDX.net About WDDX (Web Distributed Data eXchange) is a programming-language-, platform- and transport-neutral data interchange mechanism to pass data between different environments and different computers. This is WDDX implementation for .NET platforms. Support https://github.com/Bilal-S/WDDX.net/issues --- ## Privacy Policy URL: https://www.boncode.net/privacy-policy Who we are Our website address is: http://www.boncode.net. What personal data we collect and why we collect it In general we do not track any direct information about site visitors. We do maintain regular server logs that inform us about environmental information such as time and date and your IP address and the page you have requested from our servers. Cookies We do not use any cookies on this site. Not needed. And you are welcome ;o) Embedded content from other websites This site does not publish 3rd party content or trackers. Analytics We occasionally look at server analytics to determine utilization. Your personal information is not shared or used during this process. How long we retain your data All logs are erased within six month of collection. What rights you have over your data If you have an account on this site, or have left comments, you can request to receive an exported file of the personal data we hold about you, including any data you have provided to us. You can also request that we erase any personal data we hold about you. This does not include any data we are obliged to keep for administrative, legal, or security purposes. Please keep in mind that we do not allow the creation of accounts or posting of comments on this site. If you are still contacting us because of the paragraph above assume that there was a mistake. Your contact information Please use our github link and create an issue in the appropriate project. --- ## LG V35 Home Screen Crashing with “Home is not responding.” message URL: https://www.boncode.net/lg-v35-home-screen-crashing-with-home Date: 2020-10-16 I like my LG V 35 Android phone. It is fast, has a kick-ass sound chip and worked perfectly for the longest time. But, all of a sudden it would not open the Home screen (pressing on circle from bottom phone menu) anymore.This should take half a second at most, it started taking 30s plus, with screen turning black. The Home screen would, then, completely reload.The message "Home screen is not responding. Do you want to continue to wait or quit?" would sometimes appear.I rebooted and it would work for a bit. Started to delete downloaded apps. Looking at Internet boards to see if this problem has been encountered by others. It did not seem like others were seeing this.I was getting desperate since the only other solution suggested was to reset phone back to factory settings.Last try using safe-mode to double check things. Unfortunately, the behavior did not go away in safe-mode. This made me look into the core applications that are shipped with the phone, since in safe-mode, nothing else is running.More twiddling and experimenting followed.The solutions was simple but indicated a bug in the Google Mail application when working with Office 365 email accounts. I removed a Microsoft Office 365 account I had recently added. When Google Mail was connected to this account it would hang up the phone's home screen. Making the phone nearly unusable since you cannot effective navigate between apps.Odd.I downloaded the Office Outlook for Mobile app for my office 365 account and my phone works again. I can check the email without hanging up my phone.If you are finding yourself in a similar situation I hope this helps.Cheers,Bilal --- ## ReactNative: Quickly integrate contactless payments into your react-native projects URL: https://www.boncode.net/reactnative-quickly-integrate Date: 2020-06-16 Quickly integrate contactless payments into your react-native projects Trying to go out an build a contactless payment solution from scratch is not something that everyone has the time and gumption to do. As far as approach there are principally two successful approaches to contactless one can follow. The RFC and the QR methodology. The RFC Methodology This ist the incumbent process in most of Europe and North America. Buyers use an RFC chip based Credit or Debit card or mobile device. Buyers swipe the device over a specialized card reader and seller, then, connects to card or payment processor. Popular implementations of this in the US for mobile devices are represented by Apple Pay and Google Pay. The issue for us what that this method had a few drawbacks: We needed to have special hardware. Some of which has be rented on a monthly basis by the seller (merchant). It really wasn't completely touch free. Debit cards still required touching the seller terminals. Other terminals required confirmations on occasion. Getting up and running in a real world store was not a matter of hours, but weeks and months. The advantages were that users mostly are familiar with the payment processes in the US. The QR Methodology This is the Asian model and very popular in China. Both AliPay and WeChat pay and some others use this as their standard of starting the payment processing cycle. The drawbacks here are users in US and Europe are less familiar with this methodology then they are with others though this is quickly changing. We see more users becoming familiar with QRs for other purposes besides advertising. Users now see them in restaurants for menu lookup and on rentals when renting scooters or bikes. Thus the drawbacks: a) User familiarity with process b) Since processing occurs on different device than payment initiation closing the payment loop requires effort on programmers. The advantages are that this, when done right, is: a) Very quick to implement since no other hardware is needed b) Very inexpensive for seller (merchants) c) Can be truly contactless even with debit cards d) Can close the payment loop even when process is distributed across devices. Thus, in this tutorial we will focus on QR based contactless payments and show you how to quickly get started using them in your react-native based mobile applications. We use the XcooBee contactless payments since it needs very little effort while providing many options as well as the ability to close the payment notification loop. capabilities and programming in the app. Getting Started from Scratch Prerequisites: Node 12 Free Stripe account Free XcooBee Professional account Setting up Payment Processing Backend In our example, you will need a XcooBee Professional account and a Stripe account. Both of these are free to setup. Use the video tutorials or web tutorial to configure your first XcooBee Payment Project. This sets up you base infrastructure to process payments for your app. This is what you will need to do all the back-end processing. The App You can use create react native (CRA) or Expo project as baseline for our example. We will use Expo based version. If you have never installed expo first install the command line tools: npm install expo-cli --global Create Your Expo Project Creating your expo project is also straight forward. expo init myPayProject => select blank (with Typescript) cd myPayProject expo start The last command should start a expo session with your expo app. Install libraries Now that we have a base app lets add the needed libraries yarn add react-native-svg => adds needed SVG support for vector graphics yarn add @xcoobee/react-native-xcoobee-payment-sdk => adds the XcooBee libraries App.tsx There is only one file that we need to change. That is App.tsx. Add import statement to your import section. import XcooBeePaySDK from '@xcoobee/react-native-xcoobee-payment-sdk'; Follow this with initial configuration of the payment SDK. Here is where you could set Expo Install Id etc. if you need to communicate back to your device about success and failure. For our purposes the only needed config items are campaignId and formId. You can find these values in your XcooBee Payment Project summary page. Replace your values instead of using the example values. XcooBeePaySDK.setSystemConfig({ campaignId: 'e98.eg0000000', formId: 't000' }); The remainder of the code is only a few <Text> to display labels, one <TextInput> to have the user enter the amount they wish to charge. The default is $1. Your App.tsx should look like this: import React from 'react'; import { StyleSheet, Text, TextInput, View } from 'react-native'; import XcooBeePaySDK from '@xcoobee/react-native-xcoobee-payment-sdk'; // TODO: replace with actual values from XcooBee Payment Project // Open your payment project in edit mode and review the summary screen XcooBeePaySDK.setSystemConfig({ campaignId: 'e98.eg0000000', formId: 't000' }); export default function App() { const [chargeAmount, setText] = React.useState('1.00'); const XcooBeePayQR = XcooBeePaySDK.createPayQR(parseFloat(chargeAmount)); return ( <View style={styles.container}> <Text> How much do you want to charge: </Text> <TextInput defaultValue='1.00' style={{textAlign:'right' }} onChangeText={text => setText(text)} value={chargeAmount} /> <Text style={{ marginBottom: 20, marginTop: 20 }}>Please scan and pay</Text> {XcooBeePayQR} <Text>powered by XcooBee</Text> </View> ); } Most of this is boilerplate generated by Expo during project creation. With this line we define the QR object and amount we want to represent: const XcooBeePayQR = XcooBeePaySDK.createPayQR(parseFloat(chargeAmount) where the createPayQR is the main function from the Payment SDK and chargeAmount is the amount we wish to charge buyer-user. See the Payment SDK documentation for additional options of types of QRs that can be generated and call options. When we wish to render we use the QR object like this {XcooBeePayQR}. This will add the QR in your current render container. Here is the application when running (this example uses invalid project codes so the payment cycle cannot be started): Using our Pre-Build example Of course we have already pre-build app you can experiment with if you do not want to go through all the steps. You will still need a XcooBee Payment Project setup completed if you want to process payments (test or live). Please replace the campaign Id and form id in App.tsx Expo Code GitHub Example You can also clone this to your local machine like so: git clone https://github.com/XcooBee/example-payment-sdk-react-native.git Congratulations This is all it takes to have an app that can accept contactless payments. Of course, there are many more options for QR and direct Payment URL generations than this sample can show. Feel free to experiment with the XcooBee Payment SDK, XcooBee Professional Account, and Stripe or Paypal payment processing. Pro tip: If you use Stripe test accounts or Paypal Sandbox accounts you will not incur any XcooBee charges either. You can experiment and refine from here. Cheers, Bilal --- ## node: creating a debugger setup for visual studio code and mochajs for typescript tests URL: https://www.boncode.net/node-creating-debugger-setup-for-visual Date: 2017-04-24 The title of the post says everything that I wanted to say. I have been looking at how to create a more streamlined environment for my nodejs typescript development. I was specifically interested in how to start only a specific test with the interactive debugger. I did not want to change the launch config every time I worked on a new test and I also wanted to handle mocha test  written in typescript. I normally have a tsc process started in separate command window running tsc -w command.This watches all files and compiles when needed. Here are the changes I made to Visual Studio Code and my environment. In my project I installed: typescript mocha mocha-typescript I decided to hide all TypeScript generated files via adding a files.exclude directive to my USER SETTING  (access via File:Preferences:Settings), like so: "files.exclude": { "**/.git": true, "**/.svn": true, "**/.hg": true, "**/CVS": true, "**/.DS_Store": true, "**/*.js.map": true, "**/*.js": { "when": "$(basename).ts"} } Then came the harder part. Finding a launch.config elements that would work (access via Debug:Open Configurations). I wanted to be able to open the debug pane and open the typescript test file I was working on, set breakpoints and click on "Start Debugging" button (green play button) and have the process kick off correctly. This was not as trivial as I initially envisioned and much googling and blog reading ensued. Here is the launch.config segment that worked for me. { "type": "node", "request": "launch", "name": "Debug TS mocha", "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", "stopOnEntry": false, "args": ["${fileBasenameNoExtension}.js","--no-timeouts", "--trace-warnings","--colors"], "cwd": "${fileDirname}", "sourceMaps": true, "outFiles": [], "env": { "NODE_ENV": "testing"} } This works well with standard mocha js test as well as typescript test files. For typescript you need to either have a watcher going or add a preprocess to the launch.config that transpiles your typescript first. Hope this will save someone the head scratching I went though. Cheers, B. --- ## node: A deeper look into npm (Node Package Manager) URL: https://www.boncode.net/node-deeper-look-into-npm-node-package Date: 2017-03-09 Our topic for our last NodeJs user-group meeting was npm. npm is automatically included when Node.js is installed. npm consists of a command line client and a remote repository. The command line client, of course, interacts with the remote registry. This combination allows users to consume and distribute JavaScript modules that are available in the repo. It was created in response to what its creator said "module packaging done terribly". There are many elements in this toolbox, did you know you can use npm without node?? Here are the slides of our deep dive. Hopefully it gave all of you who attended a better understanding a few helpful tips and tricks. Slides Best, B. --- ## nodejs: Continuous Code Deployment using Node.js and AWS Stack URL: https://www.boncode.net/nodejs-continuous-code-deployment-using Date: 2016-09-15 Yesterday we had our monthly Node.js usergroup meetup. I want to thank all for coming and exchanging interesting ideas for us to ponder. We looked into how to create a complete deployment cycle using cloud technologies to support our node development. We reviewed the complete process (build, test, deploy) and how tools like: - AWS CloudPipeline - AWS CodeCommit - EBS (Elastic Bean Stalk) We also used Solano Labs CI build service which is a cloud based alternative to build tool like Jenkins. Building a continuous deployment cycle can change the game for even small shops to roll out quality code from development to production in very little time. Here are the slides from the presentation, this will probably help those that were taking diligent notes. Most command line text are present on the slides. http://downloads.boncode.net/downloads/CharlotteNodeJSSeptember2016.pdf Cheers. B. --- ## serverless: Serverless Framework and ethics vs the shiny object dilemma URL: https://www.boncode.net/serverless-serverless-framework-and Date: 2016-09-10 For the last little while I was working on serverless concepts and exploring the Serverless Framework. It allows me to automate many manual steps but at the same time  it also imposes its way of thinking. Thus, it is a highly opinionated framework. Though one can be of different opinions some of the good things provided by this framework are the ability to organize your project locally, abstract configuration, and deploy to different clouds from the command line. The local development and testing paradigm is still rough and docs and examples are rather high level in many places. It is also very much at the beginning stages with version 1.0 just about to be released. As such it has an enthusiastic crew with a lot of passion to push things forward. So, in short it is the new shiny thing that is cool and thus enjoys mindshare and interest. In general that is a good thing. In particular, I can already see that there are cracks in the foundation. Two things in particular come to mind: A) Dogma  There is a sense of "we know better what you need" that permeates much of the later work on this framework. Whether it is through heavy configuration driven mechanisms in lieu of any convention elements or the careless breaking of implementation from earlier beta releases. For example, here is just a sprinkling of frameworks that believe in less configuration is better: Apache Maven Appcelerator's Titanium Alloy ASP.NET MVC CakePHP ColdBox Platform Contao Crosslight Durandal (JavaScript SPA Framework) Ember.js Enduro.js Grails Java Platform, Enterprise Edition Laravel Lift (web framework) Meteor (web framework) Play Framework Roxy rest-API Ruby on Rails Sails (web framework) Spring Framework Symfony Yii This does not appear to be relevant to the current team and my fear is that the shininess will not overcome the effort it takes to maintain this when an alternate framework emerges. Ignorance in this case is not bliss. B) Ethics of Tracking The framework uses automatic enabled tracking of usage data. To discover this you will need to dig deep into docs and code. I understand that this is anonymous, however, this is not the way to approach the issue. Take Apple's location tracking for example, it is anonymous as well. How good do you feel about it? For me the issue is with the enabled by default attitude. It is the complete undermining of faith of the user community. I believe firmly that any company making the automatic assumption of collecting data about me is living on the edge of ethics. Rather than playing in the muck, I would like to encourage the team to elevate themselves from questionable practices. There is time, and there are better alternatives. Yes, you can disable all this once you find out where in the documentation it is hidden and run the right commands. This is not the point. If you don't ask me assume that you should not do it. Here is the disable command if you are looking for it (run against all instances and all machines that you own): $ serverless tracking --disable Conclusions So in short, this framework has potential but it is sliding into the area of big, obtuse, and rather in-the-way-of-the-task with ethical dangerous undertones before even hitting version one. These are achievements we should not be proud off given the great promise that it has. If you have a project that is small or medium sized there are alternatives that work equally well and don't involve you sharing your personal command history. You still get automation and deployment in place with full control. Look at connecting AWS Code Commit to Lambda through Continuous Integration Pipelines via CodePipeline. That is some sweet stuff. I am planning on outlining how to do this in more detail in later posts. I will also put some things on serverless how-tos as contrast. There is good stuff there so an eye should be kept on it. Cheers, B. --- ## node: April 2016 Charlotte Node.js User Group material URL: https://www.boncode.net/node-april-2016-charlotte-nodejs-user Date: 2016-04-14 Folks please find the links to the presentation materials and code samples from our April 2016 Node.js meeting. I hope this will get you kickstarted with node: The presentation slides The sample code Here again the objectives from out meetup "Kicking it with Node, starter edition" : By popular demand we will focus our sessions on how the node ecosystem works. This will include the setup of the environment the idiosyncrasies of JavaScript and base understanding of the event loop and asynchronicity. So in the next session we will look at some of this: installing Node.js  understanding async tasks  understanding the event loop  what are callbacks   creating projects  understanding node modules and packages   organizing code   writing your own module  what is the package.json file  managing 3rd party packages with npm  the require system  exploring core module examples in node Cheers, B. --- ## node: Easier debugging of nodeunit with node-inspector on Windows URL: https://www.boncode.net/node-easier-debugging-of-node-unit-on Date: 2015-11-11 I was exploring how to get insight into a piece of JS code running on NodeJS. All the things were there but for some reason the unit tests were not behaving correctly. To debug this using node-inspector seem to be the logical choice but I could not find an easy way avenue to get things started. I would normally start my unit test pointing nodeunit to a directory using the windows command that becomes available after installing nodeunit via npm globally: c:\> nodeunit /test This would run through all the unit tests in the /test directory. I wanted a similar mechanism when I needed to run debugging. Googling things was not very helpful as all the examples I found were OSX or Linux specific. However, the solution in the end was fairly simple. Here are the steps from the beginning: a) install node-inspector globally c:\> npm install -g node-inspector b) install nodeunit globally c:\> npm install -g nodeunit c) locate the nodeunit command file normally somewhere like C:\Users\[logged in user]\AppData\Roaming\npm\nodeunit.cmd. Or you can use the "where" command like so: c:\> where nodeunit d) use a text editor like notepad to open the command file e) change the nodeunit command file by adding the debug flags (--debug-brk) and save as nodeunit-debug.cmd. Here is the content of the fully changed command file: @IF EXIST "%~dp0\node.exe" (   "%~dp0\node.exe" "--debug-brk %~dp0\node_modules\nodeunit\bin\nodeunit" %* ) ELSE (   @SETLOCAL   @SET PATHEXT=%PATHEXT:;.JS;=;%   node --debug-brk "%~dp0\node_modules\nodeunit\bin\nodeunit" %* ) You are done with your setup config. Thereafter you only need to use the new debug command when you want to debug test cases. a) run your tests with new nodeunit-debug command you just created. You should, of course, do so in the directory of your application rather than in the root of the drive. Assuming that all your unit tests are under a /test subdirectory you could do it like so: c:\[app dir]> nodeunit-debug /test b) in second command window run node inspector instance and inspect code in browser (Chrome) c:\> node-inspector c) open chrome to debug your code (http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858) Here is an image of a,b, and c steps in action: That is it. Cheers, B. --- ## JQM: A mini MVC Application Structure using jQuery Mobile and RequireJS URL: https://www.boncode.net/jqm-simple-application-structure-using Date: 2015-07-15 The Rational When it comes to the power jQuery Mobile (jqm) to help us organize our code we could pretty much say it in one hyphened word: "non-existent". How could this pass with such a popular library. Well, the simple answer is that it is by design. This does not mean, however, that you should not organize your jqm code projects. You are free to use any JavaScript organizing principle or helper library, e.g. BackBone or Ember, you like. Jqm's  focus is the page paradigm and rendering of touch friendly UI. This, of course, does mean that you have your work cut out for you to make decisions surrounding your project. Looking at very common pattern of jqm apps, they tend to be an amalgamation of different libraries that have many layers of code and logic that needs to be organized. And, needless to say, there is always seems to be a little bit of overlap in library's coverage, e.g. if you used Backbone for route handling, we will need to turn off the native jqm methodology etc. In the particular approach I am outlining in this post, the goal was to use minimal amount of libraries while still creating convention based organization of code, ui, and data. We should be able to split our program into distinct parts that the browser can load when needed. This will help us in following manner: decoupling of presentation and logic modular JavaScript code decoupling of the page paradigm from singular page apps organization of code by convention Overall, the maintenance of our program should be easier, while adding new parts becomes child-play ;o) After a little experimentation, I decided the only thing needed was a little extra JavaScript and the RequireJS library. Let me explain how. The Setup Standard application initialization occurs through the index.html page. However, unlike most JS apps there is only one <script> tag and that tag loads RequireJS. Thereafter the application parts are either loaded by RequireJS or JQM page loader. Thus, the script tag jungle is avoided. Clean abstractions of dependencies and libraries are all captured in the RequireJS config file. Since this is a sample app it makes liberal use of console.log function. <script data-main="app/config" src="libs/require.js"></script> Also something that is different here is the externalized page header. I did not add an externalized page footer which can be easily done but was not needed for my example. An externalized header can easily be repeated on each subsequently loaded jqm page and thus we can focus on the page content. We will still change the header display dynamically and add proper navigation as we move between pages. <!-- external header used on all pages we will hide buttons dynamically --> <header data-theme="b" data-role="header" data-title="Simple App" data-position="fixed"> <a id="btnHome" data-rel="back" data-transition="slide" class="ui-btn ui-shadow ui-corner-all ui-icon-arrow-l ui-btn-icon-notext ui-btn-inline" title="move back">back</a> <h1></h1> <a href="#info" id="btnInfo" class="ui-btn-right ui-btn ui-btn-inline ui-btn-icon-notext ui-mini ui-corner-all ui-icon-info" title="">Info</a> </header> The Application Structure The application is structured in such a fashion that a certain convention can be observed. The main directories under /app are controllers data pages services stores All code files except the RequireJS config file are in a slightly modified JavaScript AMD Module format.We are also caching jqm views (pages) once they have been loaded using the jqm domCache directive: $.mobile.page.prototype.options.domCache = true; controllers This is where we place all controller logic for our views. I maintained a convention where views do not have any logic or binding and minimal links. Controllers are automatically loaded and initialized based on the view (page) that is being requested. The app will check for a similarly named controller and start the process. Thus, all page behavior, event binding, business logic would be handled here. If the controller exports (or exposes) a function named "init", that function will be called after each page load or display. The overall convention for the controller loading process and application behavior are coded into start.js module. It acts as the overall controller for the application. Here is the basic controller construct example. //controller sample define( function() { console.log("empty controller loaded"); //public (export) return { init: function(){ console.log("init was called") } } }); data I have placed a file containing a json array of objects into this file. Thus, we can refer to this as our "database". This is not a convention that is enforced on the code layer. I chose to abstract data in this fashion. It could easily be extended to be the connection layer to a database API etc. pages The pages in our app are the view of the MVC model. I chose to use very simple views. These are snippets of HTML just with the JQM markup needed to render a basic skeleton. Logic that changes the view is either in controller or services layer. Here is an example of a view. It is just the date-role="page" part of the jqm html markup. <section data-role="page" id="composerDetail" data-title="Composer Detail"> <div role="main" class="ui-content"> <h2 id="composerName">Composer Name</h2> <hr> <!-- composer info --> <div class="ui-grid-a ui-responsive" > <div class="ui-block-a center" style="width:20%;"> <div class=""> <img id="composerImage" src="" alt="composer image" style="vertical-align: middle;"> </div> </div> <div class="ui-block-b" style="width:80%; vertical-align: top;"> <div class="ui-body ui-body-d"><p id="composerDescription">composer information</p></div> </div> </div> <!-- buttons --> <div class="ui-grid-a center" > <div class="ui-block-a" style="width:20%;"> <div class="ui-body ui-body-d"><a data-rel="back" data-transition="slide" class="ui-btn ui-shadow ui-corner-all ui-icon-arrow-l ui-btn-icon-notext ui-btn-inline" title="Back to composer list">back to list of composers</a></div> </div> <div class="ui-block-b" style="width:80%;"> <div class="ui-body ui-body-d"> <button id="btnWiki" class="ui-btn ui-icon-arrow-u-r ui-btn-icon-right ui-corner-all" title="More information on WikiPedia" style="width:80%">WikiPedia</button> </div> </div> </div> </div> </section> services This is where I paced example services that can be used in other modules. In my case just a way to abstract jquery ajax calls and handle generic responses. But, this could be easily expanded to anything that is shareable across the modules or detailed implementation that would be make controllers large and unwieldy. This is not a enforced by code but a convention I am suggesting. It helps to separate heavy logic into distinct modules for maintainability. stores I used the stores to abstract interaction with the data layer. For example my sample ComposersDataStore.js in this project can sort the composers, return a specific one etc. This is also not enforced by code, but rather a convention I am proposing for your app build. The Init Process After loading of the index.html a list of dominoes begins to fall Require will load config.js which contains the environment definition and load dependencies.  config.js will, in turn, load the start.js module which contains our overall application controller config.js will also switch to the "main" page (view) which will trigger common actions by the overall application controller as defned in start.js:  Load the main view (main.htm) Load the main_controll.js controller Call the init function of main controller Thereafter it is up to the user and his/her interactions which pages will be loaded and which actions will be triggered. Unfortunately there seems to be a bug in the jQuery Mobile page loading (page widget) which makes initialization phase inconsistent. The process is not always kicked of correctly so it required for me to do a check in the index.html itself. If we did not find the main controller module loaded after 5 seconds, we would switch to the main view one more time, which triggers the part 3 and seems to fix things. This loaded the app consistently across all devices. setTimeout(function(){ if (!require.defined("controllers/main_controll")) { console.log("catch all triggered."); $( ":mobile-pagecontainer" ).pagecontainer( "change", "app/pages/main.htm", { showLoadMsg: true } ); } },5000) The Hook The element that drives the main convention of this app is implemented in the pagecontainerchange  event hook. This event is exposed by jQuery mobile. $(document ).on( "pagecontainerchange", function() {} Here we automatically load the appropriate controller based on the id of the view (page) and initialize and call the init() function of the module. In addition, we change display name of the view based on what is in the data-title of the jqm view definition. All this happens in the start.js application controller.  Of course, in a more opinionated implementation, additional conventions could be coded here; for example, automatic loading of data-stores and even binding of the store's fields to form elements. Thus, the concept can be expanded. Experiment and see if you could add to it. GitHub baby The complete project can be reviewed or downloaded from GitHub. I have included the libraries and versions of jQuery and RequireJS so things should be able to work out of the box: Expanded Project for Download from GitHub Enjoy, B. --- ## App Idea: CircleDJ URL: https://www.boncode.net/app-idea-circledj Date: 2015-05-23 The Idea So you have music you are listening to, you like a piece of music so much you take out your ear-buds and press them on your friends to listen to the part of the song that you like so much. You guys start chatting about how cool the song is and how some other band is equally cool. You go back and forth pulling things from your individual play lists and having fun chatting about music and friendship. The way you go about it seems rather old-school in the age of mobile tech, doesn't it? What if you had each an app loaded that could make this sharing easier, better and even more fun? What if you could comment on parts of pieces of the song as it was being played?  Even bring in other friends into a "circle" to listen to the same song as it is being played. No more sharing of ear-buds while being able to comment and recommend a dynamic playlist? Everyone in the "circle" could assume DJ duties, putting things on a queue or taking over playback directly? Initial idea assumes that songs are owned outright by all participants, but alternatives are possible where this is build to work on top of premium subscription services that give people already access to all songs in catalog. More Features Users can invite friends into special purpose circles, e.g. School, Workout etc.  You can see who is being DJ in which circle Listening and comment history is available for circle members Circle members can compare their song libaries Allow in-app purchases of "missing" songs Record snippets with comments to post on twitter or Vine Techno Mumbo Jumbo This is the section I am trying to sound edumacated. The basic principle is based on synchronized playback (stream or local) of media  (audio or video) with shared playback control. Dymanic content and control of media, e.g. different users can control speed, and location of playback and this can by dynamically changed either via an election or granting scheme. Extensions Build on a music streaming service, e.g. Pandora or Spotify This idea of "social-sharing" and "active" commenting can be extended to field of  any stream-able media, e.g.Video. If you are wanting to do similar App on the basis of YouTube or other video streaming services. Bots could partake in playback control to make recommendation to groups and playback parts or tracks. The potential exists to "redefine" radio as we know it in this format. "Radio" users could take alternate control and "DJ" or curate for specific group or at specific times for other listeners.  Feedback loop and control look can be build via twitter like services. If enough of a hastag is tweeted alongside another song specific hashtag, a bot can put the most on demand songs into the play-queue. Social Implications Circle songs and comments can be shared on twitter, facebook, etc. Big Data: comments can be analyzed for trends (frequency language, power parts in songs etc.) Song Ratings for activity types Extract snippets to post with comments Related Competitive Ideas It would be expected that streaming services will build something like this into their apps to ensure higher level of stickiness for their premium services. This could be only available for premium subscribers, inviting others to their listening circle would require subscription. Or, in a modified form without the subscription you cannot participate actively (no commenting, no DJing) Monetization The assumption here is that everyone owns a copy of the song, if not friend that wish to listen in will have to purchase the song. An affiliate payment system can be used or direct resale of music. Recomendation engines to build suggestion to the circle members for purchase. Advertising (I do not like to mention this since this seems to be overused) Subscription element to unlock features, e.g. ability to DJ for the circle In app purchase of songs DJs could be hired to remote play and interact What are these post about So, like seemingly, everyone I have been collecting ideas about apps that would be "next big thing" and promptly putting them on a shelf based on time and resource demands. I am fleshing things out in bullet points. Rough bullet points! You are free to do with it whatever tickles your fancy. I have decided to break with the cycle of selfishness and just post the ideas for anyone to use. Though I am not opposed to gazillions and instant nerd-fame, I have come to the conclusion that I rather have the idea be turned into action when I know that I will not be able to. Also I am sharing in the hopes that, even, if marginally, I am preempting the people that like to patent just about everything including how my shoe laces tie together from stifling innovation. This is prior art people. Booyah! Do you expect a return? In one word, yes! I am hoping that I get attribution credit or free coffee for life whenever one of these makes it big. You don't even have to tell me, just send me my platinum Starbucks card! Fool, this already exists! If such an idea has already been turned into reality, the world is a better place ! Share it in the comment section. I do not do exhaustive research though I try to look through the app stores trying to find apps with these features. If you think my ideas are a bunch of doodoo, no need to comment, just create better ideas and make the world an even better place. Cheers, B. --- ## CF: Allowing different extensions for scheduled task log files URL: https://www.boncode.net/cf-allowing-different-extensions-for Date: 2014-11-13 This is a quick post for people that run into this dilemma where there scheduled task stop working upon upgrade. They may receive this type of error in their browser: Initialization Error: Valid extensions are : log,txt. - Invalid extension of the file name. At first you go "What the Heck!". Then, look through gazillion lines of code to find where we could have produced this error and could not pin-point it. Then, more digging to find the culprit: With the advent of ColdFusion 10 & 11 and the exposure of the scheduled task vulnerability there was a change to what extensions where supported for your log files when you schedule tasks. As a security element these files can only be log and txt files. However, the raw capture of the task run is normally neither, more often than not, especially with debug for the local IP enabled the output is HTML. Thus, we have, now, for many years, used htm as the preferred extension, since the raw capture of the task run is HTML, thus, easy to view in the browser.  Forcing it into txt would only makes us rename the file before opening in the browser again. Nightmares of unneeded code change ensued... Fortunately, the solution seems simple enough. a) Stop the ColdFusion instance b) Find the neo-cron.xml c) find the line that read like txt,log d) add your extension to that line, e.g. txt,log,htm e) start instance Hope this helps others who give themselves the "Duh" slap. Cheers, B. --- ## CF: CCFML or Making the Case for a Different CFML Future URL: https://www.boncode.net/cf-ccfml-or-making-case-for-different Date: 2014-06-06 Looking at the demands of our enterprise and the product road-maps as far as they have been disclosed by either Railo or Adobe we discovered a gap between what we are trying to achieve and what the technology is going to offer. So, I have taken upon me to summarize a few thoughts and suggestions that I would like to share to see whether we can sway the Railo/Adobe general product direction. I believe that focusing ever more innovation resources on the concept of RAD (Rapid Application Development) and language improvements, though interesting and useful, are not making CFML standout sufficiently to make a long-term difference and detract people from leaving or encouraging  new people to join. In my opinion, the next level of server improvements need to be substantially different from other offerings and, this, in turn, requires a rethinking of what Railo/ACF offerings are. Specifically, • Abandonment of the concept of Application Servers • Remove the need for download/installs • Remove the need for server administration and management • Redefine offering as packaged “infrastructure” with smart policy and deployment • Use clear convention based guidelines for subsystems (cache, application, storage, db) Ok, now you say, what the heck are you dreaming about? Good question, that. In short, I am proposing that we work towards a true Cloud CFML platform === CCFML. Let me explain: We come from a heritage of dealing with individual servers and have embraced that concept wholeheartedly for many years. However, in the age of the cloud we should question those expectations. How much more attractive could CCFML be when you only need a github/subversion account to deploy your code and a few policy definitions on how large you want your Application to scale and how fast. When there are application problems, you can define policies how much CPU a process may consume, add more CPU cycles specifically for it, and/or cache. All automatically. You application works automatically, fully scalable, across the globe on CFML. You are kept abreast of any problems, bottlenecks and are given options to upscale CPU, refactor code, or add instances. But, best of all, you let the Cloud CFML take care of everything that a global CFML service should. You want to push a new version, just change code and click deploy/schedule button. Whatever decisions need to be made to get us this platform nirvana should be in the forefront of cfml future enhancements. This would require more standardization of convention so that we can have auto- configuration over coding whenever possible. Behavior for deployment will need to be defined and “standard conventions” documented. Here is just a selection of things that need to be answered on the way towards such a CCFML platform: - Which distributed cache to implement and deploy - Deployment system magic (version, install, upgrade, start, stop, pause engines) - How do you scale session across servers - How to communicate among cluster members - How do you join servers to clusters - How do you create a unified lightweight Application scope across the cluster, - How to measure and set time, - How to define and use a shared file-system - How do you delineate code files storage vs. user assets - How do you provide Application policy definitions for scaling - How to manage and analyze code performance - Create Application Manager (instead of Server Manager) - Assigned Server roles, e.g. stateless vs. statefull servers - Global logging and analysis - Etc., etc. There are probably many elements I don’t quite understand or have not considered. This is where I would ask for the smart people of the community to jump in, but, the point I am trying to emphasize is that future innovation should be directed towards creating such a platform rather than focusing on the minutiae of the language syntax. The CFML language is quite mature and tweaks on syntax can only have limited impact on stopping developer attrition while an easy to use application platform has the potential to attract developers. This model also provides a clear path for providers of this tech to charge for the services with the value recognition they are looking for. The good news is that we have many components already; the next step is to create the working package and provide CFML as a first class cloud service. We would not be the first, others like Microsoft with Azure and .net and the Java/Scala Play! Frameworks have already started the thought model and are getting traction. I fear that if we hesitate too long we may miss an opportunity to reverse course. I hope this is not too confusing of a ramble and I am looking forward to feedback. -Bilal --- ## AWS: Cache Me If You Can! Getting Started with Elasticache. URL: https://www.boncode.net/aws-cache-me-if-you-can-getting-started Date: 2013-10-25 Here are the presentation slides from our monthly Charlotte Cloud Computing Meetup and AWS Charlotte Meetup meeting. Application cache has the potential to tremendously speed up your response times. Putting a cache infrastructure together on the other hand may not be for the faint of heart.  In this meetup we will investigate the use of Amazon ElastiCache. Amazon ElastiCache is a web service that makes it easy to deploy, operate, and scale an in-memory cache in the cloud. Cheers, B. --- ## AWS: Amazon CloudSearch — Find This! URL: https://www.boncode.net/amazon-cloudsearch-hands-on-slides Date: 2013-06-28 Since we experienced some issues with this month’s meetup I am publishing the presentation slides here. We may be able to run through this at a different time again. From our meetup description: So you have used SOLR and think that is the only way to go for anything search related. But, (isn't there always a but?) you are tired of maintaining infrastructure or attempting to scale this thing.  Well time to look at alternatives specifically made for the cloud.  In this meetup we will look at AWS search, which is based on A9 search technology acquired by Amazon. It does all the dirty work for you so you can focus on your facets ;o)  We will discuss the good and the bad while attempting to use examples and build a search domain. Cheers, B. --- ## CF: Railo: Using VisualVM tool to monitor running Railo servers URL: https://www.boncode.net/cf-railo-using-visualvm-tool-to-monitor Date: 2013-04-04 I had written a Adobe ColdFusion specific article on how to use the free VisualVM tool to get insight into the workings of the Java Virtual Machine. I have since been asked to provide similar guide for Railo CFML engine. The good news is that the implementation is very similar and mostly follows the same path. I will demonstrate this using Windows OS example. I assume in this example that you have used the standard Railo installer for windows. If so, here are some simple steps to use this great tool set working with Railo. 1) download java jdk also referred to as Java SE Development Kit. You can use 1.6.38 or later or 1.7.13 or later.  Again, Important to get the JDK not the JRE. http://www.oracle.com/technetwork/java/javase/downloads/ 2) Download Visual VM: https://visualvm.dev.java.net/ 3) Configure Railo jmx access: On Windows, best way is to go to Tomcat Service Control, open the Java panel and add the following to the Java Options text box: (you can change the ports etc. this is is my sample): -Dcom.sun.management.jmxremote.port=8701 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false You can decide whether to use ssl or not, and also on the port to use. If you want to use jmx authentication I would recommend you read: http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#gdenl You will need to restart your server after you have completed your changes. 4) Configure your Visual vm start up to point to your jdk if you have not set environmental variables: e.g. on Windows if you extracted the visualvm files into C:\visualvm135 and Your JDK is located in C:\Java\jdk1.7.0_13 then you can use the following command line: C:\Java\visualvm_135\bin\visualvm.exe --jdkhome "C:\Java\jdk1.7.0_13" You can also add a batch file shortcut for reuse, e.g. 5) Start up the VisualVM tool (it may have to go through calibration first, simply acknowledge), then, and establish a connection a JMX connection by right clicking on the local node and choosing "Add JMX Connection..." 6) Add connection parameters: If the server is local you can use: localhost:[port] in our case: localhost:8701 Now you should be able to monitor basic statistics of your Railo environment as it runs, and do some nifty things like forcing garbage collection and dump heap files for later analysis. Cheers, B. --- ## CF: cfObjective() 2013… talk is cheap (relatively ;o) URL: https://www.boncode.net/cf-cfobjective-2013-talk-is-cheap Date: 2013-02-11 I decided to submit my slew of topics to this year's cfObjective conference. I had many things that I wanted to investigate or thought were worth sharing... never can pick really... Fortunately for me the selection committee picked two of my submissions and, thus, if you time it right and have no better place to be, come join me at cfObjective in Minneapolis to dig into the mobile development realm ... "Hey Bilal, come to the point", you say. "What are you going to yak about, since I am biZy! With a capital Z". Well,  ok, here are the things I am going to talk about: Design MVC Mobile App Visually In Hours HTML5 / CSS3 / JavaScript Mobile Apps are becoming more popular. Unfortunately, the tools that we use to design them have not changed much. This talk is centered on using more advanced design tool such as Sencha Architect 2 to visually create front-end MVC mobile prototypes quickly in WYSIWYG fashion. We will step through the elements and create our own app and discuss native deployment options as well. We will learn how to navigate the common UI of Sencha Architect, how to start and structure an Architect project, how to create a common mobile app with navigation pattern , how to link components, how to bind data, how to deploy generated code in your project, the difference in prototyping levels and the fit of rapid prototyping tools such as Architect, and we are going to have fun creating a real working mobile app. Mobile but Secure HTML5 CSS3 applications are becoming increasingly popular for mobile platforms. An assortment of applications makes use of the mobile devices to run, but when it comes to mobile security it is a wild west, the next frontier. What can you do to create mobile or web apps with a more solid security stance and prevent your mobile software from becoming another way to hack into your servers, your customers’ data? If you don't want to be in the news as the next mobile app whose weakness a hacker group used to get sensitive data you should familiarize yourself with the mobile security tips and tricks. We will take a look at the mobile security top ten and discuss the juiciest elements such as   Insecure Data Storage, Weak Server Side Controls, Insufficient Transport Layer Protection, Client Side Injection, Poor Authorization and Authentication and ways and how to mediate them effectively. So there you have it. Hope to see you at the Mall of America in May ! Cheers, B. --- ## CF: Scheduled Task Security venerability in Adobe CF URL: https://www.boncode.net/cf-scheduled-task-security-venerability Date: 2013-01-05 Getting hit by a security vulnerability is no fun. This new one using CFIDE scheduling (http://www.adobe.com/support/security/advisories/apsa13-01.html) seems to have impacted quite a few users. This all happened around Christmas and went downhill from there most likely automatic network scanning of availability of a certain URL path followed by automated attack. http://forums.adobe.com/message/4962104 Charlie Arehart has several blog post on this topic so I am not going to expand too much: http://www.carehart.org/blog/client/index.cfm/2013/1/2/serious_security_threat http://www.carehart.org/blog/client/index.cfm/2013/1/2/Part2_serious_security_threat The old adage to lock down your server still holds but is no solace to the people that got hit since it would impact a fully patched server. The short of this is to disable access to certain CFIDE paths. This may be the practice that you already follow, then kudos!, more importantly, get the word out to other users. Let your friends know so they don't fly blind. Overall I am surprised by this vulnerability since it seems to originate from a vector that, in my mind, should require authentication or at least some sort of access control. Seemingly the scheduling of tasks is vulnerable and wide open by default. Initial thought on this: Crap! Maybe, as a community, we should vet more closely the out of the box CFML code that is being deployed. The secure stance always has been to not deploy any example and docs on production, however, this is part of the system would be required to administer it. Couple of things that I would like to delve deeper into: a) Detecting Code Compromise: In the last talk that I had presented around application security I had shown an example that can be easily implemented and allows users to detect any code change on the machine. The idea is to generate an application signature that, then, can be verified to see whether the application is still consistent with what you published. This is a simple version, you may expand and adjust. This will help you detect whether you have been compromised. You can do this against the CFIDE, Customtag, and/or any other directory you store code in. You can create separate signatures (i.e. modules) or combined ones. The goal is to quickly be able to tell whether you were hit by a zero-day vulnerability or anything else made its way onto your server that you did not expect. It involves two general steps: First run a recursive cfdirectory on your website/app and, second, create a hash from it. Something like this: <cfdirectory action="LIST" directory="c:\inetpub\wwwroot" name="myAppFiles" filter="*.cf*" recurse="Yes"> <!--- build md5 hash ---> <cfset myAppSig = Hash(SerializeJSON(myAppFiles),"MD5","us-ascii")> Then compare the generated application signature against a last known good one. This can be done on App start, or a scheduled basis, even add hock if you app is small. Here is the similar sample that stops application execution if compromised if you include it in your OnApplicationStart function: <cffunction name="OnApplicationStart"> <!--- This assumes that you have a database with a table named "appcheck" that has at least two fields id = auto number/indexed value = text (20) The first time the app starts, the valid application signature will be determined. There after the application will abort if the signature does not match. To publish new code. Clear the appcheck table or insert the new valid signature as last row. ---> <cfquery name="selCheck"> SELECT value FROM appcheck WHERE id = (SELECT Max(ID) FROM AppCheck) OR id=0 </cfquery> <!--- determine app check crossum ---> <cfdirectory name="selAppFiles" action="list" filter="*.cf*" directory="#getComponentPath()#" recurse="Yes"> <cfset strJson = SerializeJSOn(selAppFiles)> <cfset md5Hash = Hash(strJson,"MD5","us-ascii")> <cfif selCheck.RecordCount> <!--- application compromise check. We could email someone automatically, raise alarms, call the cops ---> <cfif md5Hash neq selCheck.value> Application compromised.<br/> <cfoutput> #md5Hash# -- #selCheck.value# </cfoutput> <cfabort> </cfif> </cfif> <cfquery name="insCheck"> INSERT INTO AppCheck (VALUE) VALUES ('#md5Hash#') </cfquery> </cffunction> b) Preventing people from using the vulnerability: Charlie and other have done a good job of summarizing the source and ways you can prevent the exploit. It all seems to boil down to not let users hit certain CFIDE paths: /CFIDE/administrator /CFIDE/adminapi /CFIDE/componentutils The bad thing is that using IIS/Apache facilities to lock out call URLs may not be good enough. There is the question of virtual paths and ColdFusion built in webservers that can bypass your effort. In addition, the normal Adobe CF connection between IIS and CF is using a wildcard based handling of all request. That means all requests to your website are first routed to CF/connector, even, if you ask for an image. If you know me you know I am biased, but obviously this blows big time, since it causes unnecessary processing on IIS and CF. Try to pause or stop CF and call a static HTML page on IIS or Apache, you will wait for a while. Enough of the ranting! In short, please test your lockout configs after you make changes to make sure that everything is locked out as it should be. If you are using ColdFusion 10 on IIS you also have the option to deploy my BonCode connector. It does not block static page access, or hinder non CF processing. Since its first version it had the ability to block access to administration pages; you will not be able to bypass this even if you have the built in CF webserver running (yes, you can still hit the built in webserver if you bypass IIS altogether but that would require deliberate foolishness where you have opened the non-standard port on your Windows OS and firewalls everywhere). Here is a blog post on how this feature is used to secure Railo administration pages. This method also works for OpenBD, and Adobe CF10. The installation for CF10 is not out of the box, if there is interest in this I will provide it in later versions. Also this is not officially supported by Adobe, though given the system instability issues and problems that have occurred with the supplied connector you may want to consider testing anyway. Cheers, B. --- ## Reminiscing the difficulties of predicting the future or how the iPhone 5 made it all come true URL: https://www.boncode.net/reminiscing-difficulties-of-predicting Date: 2012-11-25 A few year back, at the height of the iPod boom, I predicted its swift demise. I might have titled this said blog post something like Why the iPod must die! So back then I was predicting the death of single purpose devices such as MP3 players in general and the iPod in particular. Well... I was wrong, but not all the way. The iPod is still around, but sales are declining. As a matter of fact they have been declining every year since my prediction was made in 2008: Why do I want to warm up old toast you ask? Good question. Another thing I mentioned towards the end of the aforementioned blog post was about, how I believed, Apple could make boatloads of money, not with the iPod itself, but with the control over the connection mechanism, the 30-pin dock. Most "i" devices Apple introduced up to iPhone 4S have this connection mechanism. A whole supporting universe of accessory makers has emerged that use that 30-pin standard to connect anything from stereo systems to zebra pattern 3d printers (I made this one up, don't Google needlessly!). However, Apple, like Sun, when it missed the JVM for the trees, missed to monetize the 30-pin connector handsomely. While normally very astute in locking in consumers and partners alike, this was a big miss, indeed, for Apple. Also contributing to this was the ease with which people could reverse engineer the connector. But fret no more, under the guise of improving user experience, Apple introduced the new "lightning connector" and closed this loophole with the iPhone 5. Though I have not heard any of my friends or co-workers ever state that they had trouble or needed a new way to connect, it is now a fact of live that we will have to buy many adapters or replace existing gadgets. Now, the life of the 3rd party accessory maker has changed drastically as well. No longer can they use simple analog techniques to reverse engineer this. There is an encryption chip specific to the connector that needs to be dealt with. Why would you need an encryption chip in the docking connector? To control its use of course. IMHO this thing is so complicated that it delayed the launch of the promised lightning to Apple dock adapter. Thus, for manufacturers the only viable alternative is to check with Apple to see what the terms of licensing lightning technology would be. This, in turn, translates into revenue in the future for Apple, and my prediction made many years ago, finally comes true ! Cheers, B. --- ## CF: ColdFusion with Amazon Load Balancer (ELB) and mysterious line breaks causing “unterminated string literal” exceptions URL: https://www.boncode.net/cf-coldfusion-with-amazon-load-balancer Date: 2012-11-20 This seems like a complicated scenario at first until I started thinking about it again. You use ColdFusion in the Cloud, specifically in the Amazon cloud, you then add a load balancer in front of your servers, then you notice your JavaScript starting to error out in some browsers. You cannot explain it. Then, you spent countless hours going nuts. Here is a sample JavaScript and ColdFusion block that would break. The simple block retrieved a name from a ColdFusion function and passed it to JavaScript: <cfoutput>   <script type="text/javascript">     var myName = '#fCallForName()#';   </script> </cfoutput> The above returned this in browser lets say the name was "John" :   <script type="text/javascript">     var myName = ' John';   </script> This, in turn, throws a "unterminated string literal" exception in JavaScript because of the line break right before the name. Of course, you say, silly you, you probably doing something in CF to return a Newline character combination. Good thought! So I changed the CF side to be as simple as possible. Here is the CF code that returns an empty string; guaranteed! <cffunction name="fCallForName" returntype="string"> <cfreturn ""> </cffunction> So nope, empty string still produced new line in the JavaScript output. So a few brain cycles go by and I get to thinking to check to hit servers directly (bypassing amazon ELB altogether) and see what is returned. The return this time is enlightening, there is a blank string rather than the expected empty string, but no newline.   <script type="text/javascript">     var myName = ' ';   </script> Yeah, progress, maybe? This is different, which again it should not be. Thus, the only thing this establishes is that the Amazon load balancer (ELB) is changing the output stream somehow. Then, I also remembered an earlier blog post of mine where I outlined that CF inserts an empty space character when the function output is used directly in place in HTML context:  /cf-coldfusion-functions-and-case-of/ ... and the fog began to lift. I immediately reassigned the function output to a variable like so: <cfset userName = fCallForName()> Then, used the variable to output the content of the function: <cfset userName = fCallForName()> <cfoutput>   <script type="text/javascript">     var myName = '#userName#';   </script> </cfoutput> ...and bingo, everything started to work again. No more JavaScript errors. However the conclusions here are more scary then the error: a) ColdFusion does introduce more than just a space character when function output is used in place b) Amazon elastic load balancer makes modifications (corrections?) to the network stream and changes the output. For each in place output of function call it adds a line break. Both a) and b) should not happen, but they do ;o( At least now my pain could be your gain. Cloud pittfals, I guess...simple assumptions like surely the load balancer will not modify my data could throw you off . Cheers, B. --- ## CF: CFCamp 2012 more of everything URL: https://www.boncode.net/cf-cfcamp-2012-more-of-everything Date: 2012-10-18 CFCamp 2012 is over. It was another whirlwind affair with more people, more speakers, more topics and more sponsors. Overall a good gathering that had some nuggets to take away and think about. Thanks everyone who stayed for my late presentation on practical application security. You can download presentation slides if you want to review them at your leisure. Cheers, B. --- ## CF: CFCamp here we go URL: https://www.boncode.net/cf-cfcamp-here-we-go Date: 2012-10-12 Another year, another CFCamp. The ColdFusion faithful trek into the southerly realms of Munich, Germany to learn all about the intricacies of living the code - dream ;o) So I am my way to join the fine folks, raise a Stein, and catch up on all that is newsworthy. There will be a selection of topics on HTML5 and mobile since this is a pattern that has been steadily gaining ground among CF'ers and is reflected in this conference. In addition there is a smaller CFAcademy segment with expanded hands on training. If you are participating in Security section of CFAcademy watch this blog as I will post some course materials shortly. CFAcademy users please download your exercise materials. You will need : One of the CFML engines (Adobe, Railo, OpenBD) installed. I will use Railo to work through examples. A database: MySQL Create a data source "book1" using the sql dump. Cheers, Bilal --- ## Sencha: NCDevCon Presentation Materials URL: https://www.boncode.net/cf-ncdevcon-presentation-materials Date: 2012-09-29 Thanks everyone for attending my presentation on Sencha Architect. I hope the Movie Finder project will provide some insight into how to use Architect to build / prototype your own apps. I am taking a moment to post the materials I used; hope this makes things clear as mud :o) Presentation Slides: MVC App in Hours (pdf) Step-by-Step: Building the Movie Finder App in Sencha Architect (pdf) Cheers, B. --- ## NCDevCon 2012: Regional Developer Conference with focus on Mobile, Web, and ColdFusion URL: https://www.boncode.net/ncdevcon-2012-regional-developer Date: 2012-09-13 Ok. Now it has been a cool four years that the Triangle Area ColdFusion User’s Group (TACFUG) is putting on a conference NCDevCon 2012 (September 29./30.) for regional developers (everyone is welcome). The user group members are putting in countless volunteer hours to create a conference for developers that everyone can benefit from. Though, as every year, there is some effort to focus the presentations. This year the focus areas are Mobile, Web, and ColdFusion, though there is a good selection of general topics as well. Thus, the conference continues to manage to have broad coverage of many relevant areas of ColdFusion, Web and Mobile development while also giving beginners options for hands on sessions. All this is available for a small fee ($200) compared to $800 to $1000 of dollars we commonly pay. So this is definitely a deal in light of the knowledge that is being shared. I have been selected to do a presentation on the Mobile side. This year’s topic is “Design MVC Mobile App Visually In Hours”. I am doing a walk-through of the Sencha architect tool as well as some other GUI development for mobile. Lots of demoing so nothing will ever go wrong ;o) There is still time to book and space available so I hope to connect with everyone there. Cheers, -B --- ## CF: MXunit Automatically Generating Tests and the Challenge of Test Scope URL: https://www.boncode.net/cf-mxunit-automatically-generating Date: 2012-08-29 Let me start by saying that I like unit testing . It is very valuable tool in the arsenal of developers to fight the ever present monsters of recursion bugs and integration nightmares. However, I will also freely admit that there is no agreement on how many unit tests are ever enough. Put a three developers in a room and you will get three different answers and maybe a headache to boot. Also, in my case, the other challenge was to determine whether I had sufficient permutations of tests to verify that unit test goals could be met. Mind you that, test-coverage does not equal code coverage, but it probably is a good proxy. So, another goal of mine is to be able to think through all kinds of ways to call on code even the bad stuff and ensure that it behaves as expected. There is system in this, however, and this is what we use come up with most of the tests. With MXUnit the world of ColdFusion has had a sturdy companion to write all these nice unit tests, however, we needed more. We wanted to have a good number of  tests especially for cfc (ColdFusion components). Coming up with the variety and permutation of tests does require quite a bit of hand coding, so we were looking for an easier way. The solution we came up with was to generate test stubs. Many, many, many test stubs. We then review the cases and expand the ones we think cover the objective sufficiently. We end up deleting quite a few generated test, but this gives us a good baseline, especially for things we don't commonly unit test but we should, e.g. sending in a number when a string is expected, sending complex values, when simple ones will do and vice versa. This may not be the way you want to work all test cases but helps to take care of many. We look at a functions parameters and generate all combinations of parameters with standard and break values. This can amount to be many thousandths so use with care. The generator sample code I am attaching has been squeezed into one code file (cfm template) so it is easier to post. Place the code content into a file named "GenerateTestsPublic.cfm" under your mxunit path. Not optimal but the concepts should be visible. Take it for a spin and make adjustments. Feel free to add comments to the blog post. Happy Experimenting: GenerateTestsPublic.cfm: <!--- Generate mxUnit tests given a component name. One File per component function will be generated in this directory. Will attempt to generate all permutations possible. Random values Break Values Prefix: Test_[componentName]_[functionName].cfc An overall TestSuite will be generated TestSuite_[componentName].cfm Distributed under Apache 2 Lincese (c) 2012 Bilal Soylu ---> <!DOCTYPE HTML> <html> <head> <title>Generate MXUnit Test for Components</title> </head> <body> <CFIF IsDefined("Form.objectName") AND Trim(Form.objectName) NEQ ""> <!--- get object info ---> <cftry> <cfset objReg = CreateObject("COMPONENT","#Trim(Form.objectName)#")> <cfset stcMeta = getMetaData(objReg)> <!--- generate directory ---> <!--- generate test files ---> <!--- save object name ---> <cfscript> //save main object strName = UCase(Trim(Form.objectName)); strUseObjectNameInDir = ReplaceNoCase(strName,".","_","ALL"); strDirPrefix = "unitTests"; strHint=""; arrTestCaseNames = []; //max test cases (high number of combinations can exist intMaxCases = -1; intMaxCasesPerFile = 1000; if (IsDefined("Form.maxTests") and Val(Form.maxTests) GT 0) intMaxCases = Val(Form.maxTests); if (IsDefined("Form.maxTestsPerFile") and Val(Form.maxTestsPerFile) LT intMaxCases) intMaxCasesPerFile = Val(Form.maxTestsPerFile); //names & paths strBasePath = GetDirectoryFromPath(GetCurrentTemplatePath()) & strDirPrefix & "\"; strFilePrefix = "Test_#strUseObjectNameInDir#_"; strTestSuiteName = "TestSuite_#strUseObjectNameInDir#.cfm"; strTestSuitePath = strBasePath & strTestSuiteName; strTestCaseDirName = "TestCases_#strUseObjectNameInDir#"; strTestCaseDirPath = strBasePath & "" & strTestCaseDirName; blnComplete=false; crlf = chr(13) & chr(10); tab = chr(9); //create directory if (NOT DirectoryExists(strTestCaseDirPath)) DirectoryCreate(strTestCaseDirPath); //sample data sampleStructure= ":" & SerializeJSON({"number"=9999,'text'='my text value','dte'=Now()}); sampleArray= ":" & SerializeJSON(["a","b",33,{"number"=9999,'text'='my text value','dte'=Now()}]); sampleQuery = QueryNew(""); FastFoodArray = ["French Fries","Hot Dogs","Fried Clams","Thick Shakes"]; nColumnNumber = QueryAddColumn(sampleQuery, "FastFood", "VarChar", FastFoodArray); </cfscript> <!--- assemble files ---> <cfif IsDefined("stcMeta.Functions") AND ArrayLen(stcMeta.Functions) GT 0> <cfloop index="i" from="1" to="#ArrayLen(stcMeta.Functions)#" step="1"> <!--- each functions has its on test case. init var containers ---> <cfset stcFunc = stcMeta.Functions[i]> <cfset selParaCombinations = QueryNew("")> <cfset stcQueries = {}> <cfparam name="stcFunc.Access" default="public"> <cfif stcFunc.Access IS "public"> <cfset strMethod = UCase(stcFunc.name)> <cfset strMethodHint = ""> <cfset strTestCaseName = strFilePrefix & strMethod> <cfset strTestCaseFileName= strTestCaseDirPath & "\#strTestCaseName#.cfc"> <!--- output (bsoylu 03-29-2012) ---> <cfoutput> <br>processing: #strMethod#<br> </cfoutput> <!--- start testCase tC variable ---> <cfset genStartTc()> <!--- init ---> <cfset arrParams = stcFunc.Parameters> <!--- iterate through each paramter and set base test values ---> <cfif (ArrayLen(arrParams) GT 0)> <cfset strQList = ""> <cfloop from="1" to="#ArrayLen(arrParams)#" index="y"> <cfset stcPara = arrParams[y]> <cfset strParaName= UCase(stcPara.Name)> <!--- create query and query handle ---> <cfset stcQueries["q_#strParaName#"] = QueryNew(strParaName,"CF_SQL_VARCHAR")> <cfset selQ = stcQueries["q_#strParaName#"]> <cfset strQList = ListAppend(strQList,"q_#strParaName#")> <!--- if parameter is not required it can be null as a valid state ---> <cfif NOT (IsDefined("stcPara.Required") AND stcPara.Required)> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"NULL")> </cfif> <!--- by type ---> <!--- we prefix with equal sign if we need to eval the data later in processing ---> <!--- we prefix with colon (:) when we need to deserialize JSON ---> <cfif IsDefined("stcPara.Type")> <cfif stcPara.Type IS "numeric"> <!--- for each numeric: use max, use min, use zero, use random ---> <!--- Java Long: 9223372036854775807 and -9223372036854775808 ---> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"999999999")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"-999999999")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"0")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"#RandRange(0,999999999)#")> </cfif> <cfif stcPara.Type IS "string"> <!--- for each string: use max, use empty, use "coldFusion" ---> <cfset strLongString = RepeatString("a",4000)> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"#strLongString#")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"coldFusion")> </cfif> <cfif stcPara.Type IS "struct" OR stcPara.Type IS "any" > <!--- for each struct: use empty, use test struct ---> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,sampleStructure)> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"=StructNew()")> </cfif> <cfif stcPara.Type IS "date" > <!--- for each date: use "1/1/1980" use today use tomorrow, use 12/31/2200 ---> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"=CreateDate(1980,1,1)")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"=Now()")> <cfset tomorrow = DateAdd("d",1,Now())> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"=CreateDate(#Year(tomorrow)#,#Month(tomorrow)#,#Day(tomorrow)#)")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"=CreateDate(2200,12,31)")> </cfif> <cfif stcPara.Type IS "array" > <!--- for each array: add sample array and empty ---> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"=ArrayNew(1)")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,sampleArray)> </cfif> <cfif stcPara.Type IS "boolean" > <!--- for each bool: true/false ---> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"Yes")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,"No")> </cfif> <cfif stcPara.Type IS "query" > <!--- for each query: sample and empty ---> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,":#SerializeJSON(sampleQuery)#")> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,":#SerializeJSON(QueryNew(""))#")> </cfif> <cfelse> <!--- valid state for non-typed or unknown paramters ---> <!--- for each undefined type (any): use structure ---> <cfset QueryAddRow(selQ)> <cfset QuerySetCell(selQ,strParaName,sampleStructure)> </cfif> <!--- for the first parameter query we also set the query result. If there is only one parameter this is what will be returned ---> <cfif y IS 1> <cfset selParaCombinations = selQ> </cfif> </cfloop><!--- loop through paramters ---> <!--- build cartesian product of queries (this will show us all the needed combinations ---> <cfset qCounter = 0> <cfloop list="#strQList#" index="qName"> <cfset qCounter ++> <cfif qCounter GT 1> <!--- combine into cartesian set. We can only do two queries at a time ---> <cfset qToAdd = stcQueries[qName]> <cfquery name="selParaCombinations" dbtype="query"> SELECT DISTINCT * FROM selParaCombinations,qToAdd </cfquery> </cfif> </cfloop> <!--- determine max loop (bsoylu 03-30-2012) ---> <cfset intMaxLoop = selParaCombinations.RecordCount> <cfif intMaxCases GT 0> <cfset intMaxLoop = intMaxCases> </cfif> <cfoutput> found #selParaCombinations.RecordCount# test combinations <cfif intMaxCases GT 0 AND intMaxCases LT selParaCombinations.RecordCount> <b>only #intMaxCases#</b> will be generated </cfif> <br> </cfoutput> <cfflush> <!--- loop and generate test for file (bsoylu 03-29-2012) ---> <cfset intTestCount = 0> <cfset intFileCount = 0> <cfloop query="selParaCombinations" endrow="#intMaxLoop#"> <cfset tf=""> <cfset intTestCount ++ > <!--- create para structure (bsoylu 03-29-2012) ---> <cfset stcPara = {}> <cfloop list="#selParaCombinations.ColumnList#" index="idxCol"> <cfset strVal=Evaluate("selParaCombinations.#idxCol#")> <!--- check whether we need to further process the content (bsoylu 03-29-2012) ---> <cfif strVal neq "NULL"> <cftry> <cfif strVal is ""> <cfset stcPara[idxCol] = strVal> <cfelseif Left(strVal,1) IS ":"> <cfset stcPara[idxCol] = DeserializeJSON( Right(strVal,Len(strVal)-1))> <cfelseif Left(strVal,1) IS "="> <cfset stcPara[idxCol] = Evaluate( Right(strVal,Len(strVal)-1))> <cfelse> <cfset stcPara[idxCol] = strVal> </cfif> <cfcatch> <hr> <cfoutput>could not interpret #Right(strVal,Len(strVal)-1)#</cfoutput> </hr> <cfabort> </cfcatch> </cftry> </cfif> </cfloop> <!--- create function for this para combination (bsoylu 03-29-2012) ---> <cfset strJSON = SerializeJSON(stcPara)> <cfset tf=tf & crlf> <cfset tf=tf & crlf & tab & '<cffunction name="test_#strMethod#_#NumberFormat(selParaCombinations.CurrentRow,"00000")#" >''> <cfset tf=tf & crlf & tab & tab & '<cfset var strJSONPara =''' & strJSON &'''>''> <cfset tf=tf & crlf & tab & tab & '<cfset var response ="">''> <cfset tf=tf & crlf & tab & tab & '<cfset var argCol = DeserializeJSON(strJSONPara)>''> <cfset tf=tf & crlf & tab & tab & '<cfinvoke argumentcollection="##argCol##" component="#strName#" method="#strMethod#" returnvariable="response"/>''> <cfset tf=tf & crlf & tab & tab & '<cfset assertNotEquals( "",response,SerializeJSON(response) & " - failed call with' & Replace(strJSON,'"','""','ALL') & '")>''> <cfset tf=tf & crlf & tab & '</cffunction>''> <cfset tf=tf & crlf> <!--- add to test file content (bsoylu 03-29-2012) ---> <cfset tc=tc & crlf & tf> <cfif intTestCount mod intMaxCasesPerFile IS 0> <!--- write what we have so far (bsoylu 04-03-2012) ---> <cfset intFileCount++> <cfset strModTestCaseName = strTestCaseName & "_File" & intFileCount> <cfset tC = tC & crlf & '</cfcomponent>''> <!--- set numbered File names (bsoylu 04-03-2012) ---> <cfset strModTestCaseFileName= strTestCaseDirPath & "\#strModTestCaseName#.cfc"> <cfset ArrayAppend(arrTestCaseNames,strModTestCaseName)> <cffile action="WRITE" file="#strModTestCaseFileName#" output="#tc#" addnewline="No"> <cfoutput>generated sub case file: #strModTestCaseName#<br></cfoutput> <!--- reset tc for next file (bsoylu 04-03-2012) ---> <cfset genStartTc("_File" & intFileCount + 1)> </cfif> </cfloop> <!--- set parameters (bsoylu 03-29-2012) ---> </cfif> <!--- we have parameters ---> <!--- complete the last file (bsoylu 04-03-2012) ---> <cfset tC = tC & crlf & '</cfcomponent>''> <cfset ArrayAppend(arrTestCaseNames,strTestCaseName)> <!--- write test case ---> <cffile action="WRITE" file="#strTestCaseFileName#" output="#tc#" addnewline="No"> <cfoutput>generated last case file: #strTestCaseName#<br></cfoutput> </cfif> <!--- public function ---> </cfloop> <!--- loop through functions ---> <!--- generate test suite file ---> <cfset genTestSuite()> <cfset blnComplete = true> </cfif> <hr> <cfcatch type="Any"> <font color="red" size="+2"> There was an error. Please ensure that your component is located in the correct directory: <BR> </font> <table cellspacing="2" cellpadding="2" border="1"> <tr> <td><cfdump var="#cfcatch#"> </td> </tr> </table> <HR color="#ff0000" noshade> </cfcatch> </cftry> </CFIF> <cffunction name="genTestSuite"> <cfset var tcName =""> <cfset tf = crlf> <cfset tf=tf & crlf & '<cfparam name="URL.output" default="extjs">''> <cfset tf=tf & crlf & '<cfset testSuitePath = "mxunit.framework.TestSuite" >''> <cfset tf=tf & crlf & '<cfset testSuite = createObject("component", testSuitePath).TestSuite() >''> <cfloop from="1" to="#ArrayLen(arrTestCaseNames)#" index="idxArr"> <cfset tcName = arrTestCaseNames[idxArr]> <cfset tf=tf & crlf & '<cfset uTest = createObject("component", "#strTestCaseDirName#.#tcName#")>''> <cfset tf=tf & crlf & '<cfset testSuite.addAll("#tcName#", uTest) >''> <cfset tf=tf & crlf> </cfloop> <cfset tf=tf & crlf> <cfset tf=tf & crlf & '<cfset results = testSuite.run() >''> <cfset tf=tf & crlf & '<cfset out = results.getResultsOutput(URL.output)>''> <cfset tf=tf & crlf & '<cfif NOT IsSimpleValue(out)>''> <cfset tf=tf & crlf & tab & '<cfdump var="##out##">''> <cfset tf=tf & crlf & '<cfelse>''> <cfset tf=tf & crlf & tab & '<cfoutput>'##out##</cfoutput>'> <cfset tf=tf & crlf & '</cfif>''> <!--- loop through and add tests (bsoylu 03-29-2012) ---> <cffile action="WRITE" output="#tf#" file="#strTestSuitePath#" addnewline="No"> </cffunction> <cffunction name="genStartTc"> <cfargument name="strModifier" type="string" default="" hint="modifier for component name"> <!--- start testCase tC ---> <cfset tC = '<cfcomponent displayname="MxunitTestCase_#strTestCaseName##Arguments.strModifier#" extends="mxunit.framework.TestCase">''> <!--- empty call no parameters ---> <cfif Arguments.strModifier IS ""> <cfset tc=tc & crlf & tab & '<cffunction name="testNoParams_#strMethod#" >''> <cfset tc=tc & crlf & tab & tab & '<cfset var response ="">''> <cfset tc=tc & crlf & tab & tab & '<cfinvoke component="#strName#" method="#strMethod#" returnvariable="response"/>''> <cfset tc=tc & crlf & tab & tab & '<cfset assertNotEquals( "",response,"No parameter call failed")>''> <cfset tc=tc & crlf & tab & '</cffunction>''> </cfif> </cffunction> <cfif IsDefined("blnComplete") and blnComplete> <font size="+2" color="#008000"> <cfoutput> Successfully generated Test Suite for Component [#UCase(Form.objectName)#]. <BR> Test suite file : <a href="#strDirPrefix#/#strTestSuiteName#" target="_blank" title="run tests">[#strTestSuitePath#]</a> <BR> Please review and adjust specific test cases. </cfoutput> </font> <cfabort> </cfif> <h2>Welcome</h2> <BR> This program will help you generate mxUnit test cases. It requires access to components to be analyzed. <BR> After initial generation you should make changes as the assertion are generic. The objective is provide broad test coverage. <HR> Behavior Notes <BR> <PRE> All files will be generated in the "unitTests" subdirectory based on the initial directory this template is run from Will attempt to generate all permutations possible. Random values Break Values Test File Name: &nbsp;&nbsp;TestCases_[componentName]\Test_[componentName]_[functionName].cfc If multiple files are generated per function, a File[n] postfix wil be added except the last one: &nbsp;&nbsp;TestCases_[componentName]\Test_[componentName]_[functionName]_File[n].cfc An overall TestSuite will be generated Test Suite name: TestSuite_[componentName].cfm </PRE> <form method="post" action="GenerateTestsPublic.cfm"> <table cellspacing="2" cellpadding="2" border="0"> <tr> <td>Component Path from the webroot (e.g. component located [root]/myweb/cfcs/foo.cfc would be myweb.cfcs.foo)</td> <td><input type="Text" name="objectName" value=""></td> </tr> <tr> <td>Max Number of Test Cases per File (same function)</td> <td><input type="Text" name="maxTestsPerFile" value="1000"> (multiple files will be generated if more than this number)</td> </tr> <tr> <td>Max Number of Test Cases for a Function</td> <td><input type="Text" name="maxTests" value="5000"></td> </tr> <tr> <td></td> <td><input type="submit" name="submit" value="submit"></td> </tr> </table> </form> </body> </html> Cheers, B. --- ## CF: ColdFusion 10 on Tomcat and the CGI mistery URL: https://www.boncode.net/cf-coldfusion-10-on-tomcat-and-cgi Date: 2012-07-17 One of the things I applaud Adobe for in the new release of ColdFusion is to have the stomach to change the  underlying Application container. Moving from JRUN to Tomcat is the right step. However, as part of the move, there still seems to be some mystery surrounding what this means. As pointed out previously by myself, Rupesh Kumar, has published a good primer on the differences, but also introduced some questions which I did not find answers for. So nothing like the present to go and dig. More specifically he points out that Adobe has made changes (enhancements) to Tomcat that allow it to work hand in hand with their connectors to get more data to the servlet engine; this, according to him, would not be available if you ran a deployment of CF10 on standard Tomcat. Of course, I wondered, what in particular would not be available and ran some tests. I used the following scenarios (all on Windows 2008 R2): a) Standard Install of CF 10 with Adobe ISAPI connector and IIS. b) Standard Install of CF 10 with BonCode connector and IIS. c) Tomcat WAR deployment of CF with BonCode connector and IIS. d) Tomcat WAR Deployment using Tomcat web server (Coyote) I configured the BonCode connector for best alignment with Adobe as outlined in my previous blog post. I admit that I did not try to use the Apache Tomcat  regular ISAPI redirector, since it would have not worked for scenario a) and b) and I assume that there are differences there. I also did not try Apache HTTPD webserver scenarios. I arrived at my conclusions by using a sophisticated setup ;o) I simply dumped the CGI scope and the count of CGI variables, then compare the dump files. The dump files in the download  zip document reflect the output for the scenarios above. However, overall I was not able to discover large differences in the CGI scope among the different approaches for running ColdFusion 10. The results for scenarios a) - c) were identical, and while scenario d) showed differences, they were minimal. I attribute this to Tomcat's native web-server's interpretation of HTTP protocol. It chooses to interpret traffic and headers slightly differently. The differences in scenario d) relate to the following  CGI variables: Content_Length Context_Path Gateway_Interface HTTPS Thus, if you wish to keep your coding the same, select options a)-c) while exercising some care in the use of Apache Coyote as webserver for ColdFusion 10. Cheers, B. --- ## CF: ColdFusion 10 experimenting with alternate connector with IIS URL: https://www.boncode.net/cf-coldfusion-10-experimenting-with Date: 2012-06-28 A more up-to-date article about this can be found here: http://www.boncode.net/boncode-connector/using-boncode-with-adobe-coldfusion If you know me, you know I really don't like the ISAPI connector Apache Tomcat has been using for ages to allow for connectivity between Apache Tomcat and IIS. This annoyed me sooo much I went to create an alternative with the BonCode connector. When Adobe released ColdFusion 10, however, they built their connection mechanism on top of the original ISAPI connector for IIS. In addition, they made modifications to both the Tomcat server code and the ISAPI connector code to accommodate their particular needs. The upside of this is things continue to mostly work like they have in the previous iterations, with maybe the only exception being, that you can no longer use CFFLUSH with the out of the box setup. You actually have to disable connector buffering (this has other side effects that you maybe OK with maybe not). To do so go to {CF-Home}/config/wscoonfig/{connector-no}/isapi_redirect.properties. Change iis_buffer_enable to false and restart the IIS. By now you also know that Adobe does not recommend you use the default Tomcat instance to host anything else besides ColdFusion. A good blog post: "What’s the deal with Tomcat in ColdFusion 10?"  by Rupesh Kumar explains this in more detail. On the other side, if you want to easily use one IIS to front-end multiple tomcat instances or applications, you really have to do something about the non-standard connector that ships with CF10. Your IIS gies otherwise completely monkey-crazy if you try to work with the Adobe supplied one. Thus, time for a good experiment. I built in experimental support for the Adobe specific idiosyncrasies to the AJP protocol into the BonCode connector with version 1.0.2 and was curious whether I could get this to work with the release version of CF10. The first step is actually to install CF10 as usual. Once the server install of CF10 is complete, however, you will need to remove the existing connector via the webserver config tool like so: Once the removal of the Adobe connector is done, you can download the BonCode connector from RiaForge connector and start the standard install. Accept all the defaults but once you get to the Tomcat information page, you will need to change the port to 8012 since this is the port CF10 will accept connections under for AJP, like so: That's all folks. Now you can configure additional sites, and tomcat instances as outlined in the connector manual and your IIS server will happily serve you. If you want to take this a little further  I would suggest a few tweaks: a) If you want CFFLUSH support, check the appropriate option during the install of the connector on the options page.This is truly implemented as HTTP flush detection, rather than disabling of buffers and will not cause extra client or network overhead. b) If you want the CGI.PATH_INFO variable to be populated exactly like CF10, you will need to change the connector setting file slightly. First, find out where the setting file is located by calling this URL on the server:  http://localhost/a.cfm?BonCodeConnectorVersion=true Then, add the PathInfoHeader directive like so to the setting file: <PathInfoHeader>path-info</PathInfoHeader> c) If you want to use the same packet size that Adobe defaults to, you can also change the packet size using the PacketSize directive in the setting file like so: <PacketSize>65531</PacketSize> This reduces the number of packets exchanged between IIS and CF Tomcat but uses a larger buffer block. d) If you want to explore the full functionality of CF10 I would also recommend that you add the wildcard mappings to the appropriate sub-folders in your  CF10 site. This is used for some of its flex and background features: /CFFormGateway /flex2gateway /CFFileServlet /cfform-internal /flashservices/gateway /flex-internal /rest The directions on how to add wilcard mappings are also in the manual that is included in the download package for the BonCode connector. Happy experimenting. B. UPDATE ! UPDATE ! UPDATE ! UPDATE! -- 8/1/2012 I added a setting specifically to address the behavior of the connector for Adobe backends with version 1.0.8 of the connector. This allows the connector to be changed with only one switch and everything should fall into place: <EnableAdobeMode>True</EnableAdobeMode> UPDATES: -- 5/30/2013 Adobe made changes that are only reflected in version 1.0.15 of Boncode. If you are using any earlier version you will need to change the server.xml file normally located here: cf_root/runtime/conf/server.xml Find line similar to: <Connector port="8012" protocol="AJP/1.3" redirectPort="8443 packetSize="65531"/> And add the packetSize directive. This is not needed if you use version 1.0.15 or higher of connector. UPDATES -- 01/10/2014 More time spent going through the grunge work of analysis when people reported issues more changes discovered.  For example, the Adobe connector hard-codes but hides the packetSize attribute in tomcat. Adobe is actually using 65531 bytes as packet size now. Why? No one knows. Version 1.0.18 (to be released shortly) of the connector makes this adjustment automatically when you turn on Adobe mode so you don't get odd pages with bytes missing. This is pretty mean. I made changes accordingly to above examples. If you use standard Tomcat, but switch to Adobe mode, you will need to put this value into the Tomcat server.xml configuration file from now on. UPDATES -- 02/17/2014 Some hard core testing has gone into release 1.0.18g of the connector and as a result of feedback from the community I have removed the "experimental" moniker for CF10. Will support you all the way now ;o) UPDATES -- 10/18/2014 Please note that there are some changes to the default port used for Adobe ColdFusion 11. ColdFusion 11 uses port 8014 for AJP traffic. As usual, feedback is appreciated. Please post on the Riaforge.org site. --- ## CF: Installing ColdFusion 10 with IIS URL: https://www.boncode.net/cf-installing-coldfusion-10-with-iis Date: 2012-06-26 I thought I write a quick note on the installation of CF10 on Windows, especially if you want to use IIS7. Let's say you installed IIS with the most basic setup and the tried to install CF10. During the setup of CF10 you will be prompted at the web server selection and configuration step to install more Role Services for IIS like this: You would correctly interpret this to mean: Install: ASP.NET, ISAPI Extensions and ISAPI Filter like so: However, this is not quite accurate. Since you still will not be able to proceed.You will also need to add the CGI Role Service. Best, B. --- ## CF: breaking queries into pages of data URL: https://www.boncode.net/cf-breaking-queries-into-pages-of-data Date: 2012-06-23 Another day another problem to solve. With many more Ajax type screens, managing the data flow to the front-end needs to be baked into the core system. Otherwise, it seems, the users really do not have a care in the world about how much data they consume.... In my specific case, I am receiving a query (structured data in records), any type of query from any type of DB. I do not know the number of columns, indexes, pks or anything. The job is to be able to return a page of records from this query without going back to the database (would be hard since we don't know the database either). This could even be a QofQ, i.e. code generated, set of records. I scratched my head several times over this, but still do not think I have an elegant solution. Nonetheless, I have a working one. I wanted to avoid looping over the query itself and creating a new one record by record. I decided to use a Query of Query approach though only when needed. To do that I dynamically attach another column to the original query that I am using as primary key. Then, I am calculating the start and end records for the page and using a QoQ to just return the ones requested for the Page. <cffunction name="getQueryPage" access="public" returntype="query" hint="return a query with subset of records based on page argument."> <cfargument name="selRecords" required="Yes" type="query" hint="the base query with records"> <cfargument name="Page" required="no" type="numeric" default="1" hint="which page (chunk) to return"> <cfargument name="PageSize" type="numeric" default="50" hint="size of record chunk. this is also the max number of records to be returned."> <cfscript> //init stuff var dataQuery = arguments.selRecords; //realias var selReturn = dataQuery; var iPageCount = ceiling(dataQuery.recordCount/arguments.PageSize); var lstCols = dataQuery.ColumnList; // capture col list before change var blnDoSubQuery = false; var intStartRec = 0; var intEndRec = arguments.PageSize; var zzArray = ArrayNew(1); arguments.Page = int(Abs(arguments.Page)); //ensure that we have no negatives //if we request a page that is too big return last page if( arguments.Page GT iPageCount) arguments.Page = iPageCount; //attach control column to base data if calculations require it and or it is not present. if (ListFindNoCase(lstCols,"zzzPageControlCol") IS 0 AND arguments.Page GT 0) { intStartRec = 1 + ((arguments.Page -1) * arguments.PageSize); intEndRec = intStartRec + (arguments.PageSize -1); //only if the overall query has more records than requested do we need to do anything. if ( NOT (intStartRec IS 1 AND intEndRec GTE dataQuery.recordCount)) { blnDoSubQuery = true; //attach control col zzArray = ArrayNew(1); //if we do not think that the passed in query is cached, we can probably use a scheme //were we only mark the records that we need to return. //however, marking all records one time is faster, if the base query is cached and repeatedly pages //need to be returned for (i=1; i LTE dataQuery.Recordcount; i++) { zzArray[i] = i; } QueryAddColumn(dataQuery,"zzzPageControlCol","Integer",zzArray); }; } </cfscript> <!--- only do subquery if needed, ideally the base query is cached somehow but that is beyond this scope (bsoylu) ---> <cfif blnDoSubQuery> <cfquery name="selReturn" dbtype="query" > SELECT #lstCols# FROM dataQuery WHERE zzzPageControlCol >= #intStartRec# AND zzzPageControlCol <= #intEndRec# </cfquery> </cfif> <cfreturn selReturn> </cffunction> Cheers, B. --- ## Sencha: Presentation Slides from SourceDevCon 2012: Combining Sencha Touch 2 and ExtJS4 into one project URL: https://www.boncode.net/sencha-presentation-slides-from Date: 2012-05-04 They said it could not be done. But for all who attended my talk at Source Dev Con 2012 about Combining your Sencha library projects into one, now know, that we can fight this fight! We even have a reasonable chance to win battles. First, thanks to all who have taken time to listen and were polite enough not to yawn in front off me (though I did not check when I turned my back). Second, if things were unclear (sometimes after listening to many people talk ceaselessly ideas get swished around the head and start chasing each other down into a land of fog and confusion ;o) please contact me and I will try my best to respond more clearly. Here is the sample code. Here are the presentation slides for your continued entertainment. Cheers, B. --- ## Sencha: Parsing Touch 2 URL: https://www.boncode.net/sencha-parsing-touch-2 Date: 2012-04-15 I started an experiment  to see whether the whole JS script code of the Sencha Touch 2 library could be parsed into a JSON representation for further analysis. After going at it a few different ways I was finally able to do it using the Esprima JS library. Here is the JSON representation of the code if you are interested and want to take a look yourself. I used this as part of analysis to compare ExtJS4 and Sencha Touch 2 class libraries. Interesting to find out what code has potential to run unmodified in both of them vs code that probably will not. Here is the link to resulting analysis spreadsheet (17KB). Overall we are looking at a good chance that things will not work; 77% of the classes in ExtJS4 do not have a representation in Sencha Touch 2. Cheers, B. Test --- ## Sencha: Charlotte User Group Meeting URL: https://www.boncode.net/sencha-our-first-user-group-meeting Date: 2012-04-13 Yesterday we had our first Sencha Charlotte Usergroup Meeting. It turned out to be productive discussions around what, when, and how we want to meet. We also were able to put more meat on the bone for future presentation. Thus, this is shaping up to be a good group and I am looking forward to learn new and interesting things. Currently we have meetings scheduled until September. Here are the topics that we intend to cover: 5/31 - Expand Designer 2 Demo - Bilal 6/28 - PhoneGap - Jojo 7/26 - MVC in JS (Backbone, Sencha) - Joe  8/30 - Unit Testing w. Jasmin/ QUnit   -  Pramod 9/27 - Sencha GWT   -  Brad More detail for each of these meetings is available on our group meetup site. Cheers, B. --- ## CF: When does OnRequestEnd get executed URL: https://www.boncode.net/cf-when-does-onrequestend-get-executed Date: 2012-01-13 This is one is from my main man Kip (@kipthegreat) he ran through this exercise using Adoce CF 9. Might be helpful for others to know. Situation Does OnRequestEnd() get executed? Page calls <cfabort> tag Yes Page calls to redirect user Yes Page calls with abort="true" Yes Request exceeds timeout NO Uncaught exception NO The lesson to pay attention to is to catch and handle your exceptions ;o)  Cheers, -B --- ## JavaScript: Check whether a sub object is defined in a multi-object chain URL: https://www.boncode.net/javascript-check-whether-sub-object-is Date: 2012-01-08 When you are in JavaScript mode it is common for you to use typeof operator to see whether a given variable, object, function etc. is known to JavaScript. However, many times I find myself writing more complex code because it is a child of a child object that I need to check for a value. This makes for ugly code. Being rather simple minded I chose to Google for an obvious solution. Unfortunately, nothing was immediately available (or I might be simple missing it). Most people seem to only need to be dealing with the top level object deceleration and, thus, no need for anything else. So, to make a long story short, I created a simple helper function that does most of the work for me and cleans up the repetitive code. Feel free to use it at your leisure: /** * Take string input in varName and determine whether it is defined object in Javascript * @param {String} varName * @return {boolean} * @author Bilal Soylu */ function isDefined(varName) { var retStatus = false; if (typeof varName == "string") { try { var arrCheck = varName.split("."); var strCheckName = ""; for (var i=0; i < arrCheck.length; i++){ strCheckName = strCheckName + arrCheck[i]; //check wether this exist if (typeof eval(strCheckName) == "undefined") { //stop processing retStatus = false; break; } else { //continue checking next node retStatus = true; strCheckName = strCheckName + "."; } } } catch (e) { //any error means this var is not defined retStatus = false; } } else { throw "the varName input must be a string like myVar.someNode.anotherNode[]"; } return retStatus; } Cheers, -B. --- ## Java: Implementing PGP Single Pass Sign and Encrypt using League of Bouncy Castle library URL: https://www.boncode.net/java-implementing-pgp-single-pass-sign Date: 2012-01-02 The League of Bouncy Castle Cryptography library is chock-full of goodies but it is hard to convert what is in there to more practical examples. The example files are a solid basis but I seam to need to fiddle quite a bit until it something is usable for me. The PGP Single Pass Sign and Encrypt process is one of these things that took me for a long time to figure out. I owe much of the actual solution impementation to John Opincar who solved this puzzle for C#. Here is my implementation for Java: /** * */ package net.boncode.crypto; //bouncy castle imports import org.bouncycastle.bcpg.ArmoredOutputStream; import org.bouncycastle.bcpg.CompressionAlgorithmTags; import org.bouncycastle.bcpg.HashAlgorithmTags; import org.bouncycastle.bcpg.SymmetricKeyAlgorithmTags; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openpgp.PGPCompressedData; import org.bouncycastle.openpgp.PGPCompressedDataGenerator; import org.bouncycastle.openpgp.PGPEncryptedDataGenerator; import org.bouncycastle.openpgp.PGPEncryptedDataList; import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPLiteralData; import org.bouncycastle.openpgp.PGPLiteralDataGenerator; import org.bouncycastle.openpgp.PGPObjectFactory; import org.bouncycastle.openpgp.PGPOnePassSignature; import org.bouncycastle.openpgp.PGPOnePassSignatureList; import org.bouncycastle.openpgp.PGPPrivateKey; import org.bouncycastle.openpgp.PGPPublicKey; import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData; import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKey; import org.bouncycastle.openpgp.PGPSecretKeyRing; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSignature; import org.bouncycastle.openpgp.PGPSignatureGenerator; import org.bouncycastle.openpgp.PGPSignatureList; import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator; import org.bouncycastle.openpgp.PGPUtil; //java imports import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.NoSuchProviderException; import java.security.SecureRandom; import java.security.Security; import java.util.Date; import java.util.Iterator; /** * @author Bilal Soylu * */ public class OnePassSignatureProcessor { /** * This is the primary function that will create encrypt a file and sign it * with a one pass signature. This leans on an C# example by John Opincar * @author Bilal Soylu * @param targetFileName * -- file name on drive systems that will contain encrypted content * @param embeddedFileName * -- the original file name before encryption * @param secretKeyRingInputStream * -- Private Key Ring File * @param targetFileStream * -- The stream for the encrypted target file * @param secretKeyPassphrase * -- The private key password for the key retrieved from * collection used for signing * @param signPublicKeyInputStream * -- the public key of the target recipient to be used to * encrypt the file * @throws Exception */ public void fEncryptOnePassSignatureLocal(String targetFileName, String embeddedFileName, InputStream secretKeyRingInputStream, OutputStream targetFileStream, String secretKeyPassphrase, InputStream signPublicKeyInputStream, InputStream contentStream) throws Exception { // ** INIT // read public Key from stream (file, if keyring we use the first working key) PGPPublicKey encKey = readPublicKey(signPublicKeyInputStream); // need to convert the password to a character array char[] password = secretKeyPassphrase.toCharArray(); int BUFFER_SIZE = 1 << 16; // should always be power of 2(one shifted bitwise 16 places) //for now we will always do integrity checks and armor file boolean armor = true; boolean withIntegretyCheck = true; //set default provider, we will pass this along BouncyCastleProvider bcProvider = new BouncyCastleProvider(); // armor stream if set if (armor) targetFileStream = new ArmoredOutputStream(targetFileStream); // Init encrypted data generator PGPEncryptedDataGenerator encryptedDataGenerator = new PGPEncryptedDataGenerator( SymmetricKeyAlgorithmTags.CAST5, withIntegretyCheck, new SecureRandom(), bcProvider); encryptedDataGenerator.addMethod(encKey); OutputStream encryptedOut = encryptedDataGenerator.open(targetFileStream,new byte[BUFFER_SIZE]); // start compression PGPCompressedDataGenerator compressedDataGenerator = new PGPCompressedDataGenerator( CompressionAlgorithmTags.ZIP); OutputStream compressedOut = compressedDataGenerator.open(encryptedOut); //start signature //PGPSecretKeyRingCollection pgpSecBundle = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(secretKeyRingInputStream)); //PGPSecretKey pgpSecKey = pgpSecBundle.getSecretKey(keyId); PGPSecretKey pgpSecKey = readSecretKey(secretKeyRingInputStream); if (pgpSecKey == null) throw new Exception("No secret key could be found in specified key ring collection."); PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(password,bcProvider); PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator( pgpSecKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1, bcProvider); signatureGenerator.initSign(PGPSignature.BINARY_DOCUMENT, pgpPrivKey); // iterate to find first signature to use for (@SuppressWarnings("rawtypes") Iterator i = pgpSecKey.getPublicKey().getUserIDs(); i.hasNext();) { String userId = (String) i.next(); PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator(); spGen.setSignerUserID(false, userId); signatureGenerator.setHashedSubpackets(spGen.generate()); // Just the first one! break; } signatureGenerator.generateOnePassVersion(false).encode(compressedOut); // Create the Literal Data generator output stream PGPLiteralDataGenerator literalDataGenerator = new PGPLiteralDataGenerator(); // get file handle File actualFile = new File(targetFileName); // create output stream OutputStream literalOut = literalDataGenerator.open(compressedOut, PGPLiteralData.BINARY, embeddedFileName, new Date(actualFile.lastModified()), new byte[BUFFER_SIZE]); // read input file and write to target file using a buffer byte[] buf = new byte[BUFFER_SIZE]; int len; while ((len = contentStream.read(buf, 0, buf.length)) > 0) { literalOut.write(buf, 0, len); signatureGenerator.update(buf, 0, len); } // close everything down we are done literalOut.close(); literalDataGenerator.close(); signatureGenerator.generate().encode(compressedOut); compressedOut.close(); compressedDataGenerator.close(); encryptedOut.close(); encryptedDataGenerator.close(); if (armor) targetFileStream.close(); } /** * Try to find a public key in the Key File or Key Ring File * We will use the first one for now. * @author Bilal Soylu * @param in -- File Stream to KeyRing or Key * @return first public key * @throws IOException * @throws PGPException */ private static PGPPublicKey readPublicKey(InputStream in) throws IOException, PGPException { in = PGPUtil.getDecoderStream(in); PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in); // // we are only looking for the first key that matches // // // iterate through the key rings. // Iterator rIt = pgpPub.getKeyRings(); while (rIt.hasNext()) { PGPPublicKeyRing kRing = (PGPPublicKeyRing) rIt.next(); Iterator kIt = kRing.getPublicKeys(); while (kIt.hasNext()) { PGPPublicKey k = (PGPPublicKey) kIt.next(); if (k.isEncryptionKey()) { return k; } } } throw new IllegalArgumentException( "Can't find encryption key in key ring."); } /** * Find first secret key in key ring or key file. * A secret key contains a private key that can be accessed with a password. * @author Bilal Soylu * @param in -- input Key file or key ring file * @param passwd -- password for key * @return matching private key * @throws IOException * @throws PGPException * @throws NoSuchProviderException */ private static PGPSecretKey readSecretKey(InputStream in) throws IOException, PGPException, NoSuchProviderException { PGPSecretKey sKey = null; try { in = PGPUtil.getDecoderStream(in); PGPSecretKeyRingCollection pgpPriv = new PGPSecretKeyRingCollection(in); // we just loop through the collection till we find a key suitable for // decrypt Iterator it = pgpPriv.getKeyRings(); PGPSecretKeyRing pbr = null; while (sKey == null && it.hasNext()) { Object readData = it.next(); if (readData instanceof PGPSecretKeyRing) { pbr = (PGPSecretKeyRing)readData; sKey = pbr.getSecretKey(); } } if (sKey == null) { throw new IllegalArgumentException("secret key for message not found."); } } catch (PGPException e) { System.err.println(e); if (e.getUnderlyingException() != null) { e.getUnderlyingException().printStackTrace(); } } return sKey; } /** * fDecryptOnePassSignature will decrypt a file that was encrypted using * public key, then signed with a private key as one pass signature based on * example of verifyAndDecrypt() by Raul * * @param encryptedInputStream * @param signPublicKeyInputStream * @param secretKeyInputStream * @param secretKeyPassphrase * @return * @throws Exception */ public void fDecryptOnePassSignatureLocal(InputStream encryptedInputStream, InputStream signPublicKeyInputStream, InputStream secretKeyInputStream, String secretKeyPassphrase, OutputStream targetStream) throws Exception { Security.addProvider(new BouncyCastleProvider()); // The decrypted results. // StringBuffer result = new StringBuffer(); // The private key we use to decrypt contents. PGPPrivateKey privateKey = null; // The PGP encrypted object representing the data to decrypt. PGPPublicKeyEncryptedData encryptedData = null; // Get the list of encrypted objects in the message. The first object in // the // message might be a PGP marker, however, so we skip it if necessary. PGPObjectFactory objectFactory = new PGPObjectFactory(PGPUtil.getDecoderStream(encryptedInputStream)); Object firstObject = objectFactory.nextObject(); System.out.println("firstObject is " + firstObject); PGPEncryptedDataList dataList = (PGPEncryptedDataList) (firstObject instanceof PGPEncryptedDataList ? firstObject : objectFactory.nextObject()); // Find the encrypted object associated with a private key in our key // ring. @SuppressWarnings("rawtypes") Iterator dataObjectsIterator = dataList.getEncryptedDataObjects(); PGPSecretKeyRingCollection secretKeyCollection = new PGPSecretKeyRingCollection( PGPUtil.getDecoderStream(secretKeyInputStream)); while (dataObjectsIterator.hasNext()) { encryptedData = (PGPPublicKeyEncryptedData) dataObjectsIterator.next(); System.out.println("next data object is " + encryptedData); PGPSecretKey secretKey = secretKeyCollection.getSecretKey(encryptedData.getKeyID()); if (secretKey != null) { // This object was encrypted for this key. If the passphrase is // incorrect, this will generate an error. privateKey = secretKey.extractPrivateKey(secretKeyPassphrase.toCharArray(), "BC"); break; } } if (privateKey == null) { System.out.println(); throw new RuntimeException("secret key for message not found"); } // Get a handle to the decrypted data as an input stream InputStream clearDataInputStream = encryptedData.getDataStream( privateKey, "BC"); PGPObjectFactory clearObjectFactory = new PGPObjectFactory( clearDataInputStream); Object message = clearObjectFactory.nextObject(); System.out.println("message for PGPCompressedData check is " + message); // Handle case where the data is compressed if (message instanceof PGPCompressedData) { PGPCompressedData compressedData = (PGPCompressedData) message; objectFactory = new PGPObjectFactory(compressedData.getDataStream()); message = objectFactory.nextObject(); } System.out.println("message for PGPOnePassSignature check is " + message); PGPOnePassSignature calculatedSignature = null; if (message instanceof PGPOnePassSignatureList) { calculatedSignature = ((PGPOnePassSignatureList) message).get(0); PGPPublicKeyRingCollection publicKeyRingCollection = new PGPPublicKeyRingCollection( PGPUtil.getDecoderStream(signPublicKeyInputStream)); PGPPublicKey signPublicKey = publicKeyRingCollection .getPublicKey(calculatedSignature.getKeyID()); calculatedSignature.initVerify(signPublicKey, "BC"); message = objectFactory.nextObject(); } System.out.println("message for PGPLiteralData check is " + message); // We should only have literal data, from which we can finally read the // decrypted message. if (message instanceof PGPLiteralData) { InputStream literalDataInputStream = ((PGPLiteralData) message).getInputStream(); int nextByte; while ((nextByte = literalDataInputStream.read()) >= 0) { // InputStream.read guarantees to return a byte (range 0-255), // so we // can safely cast to char. calculatedSignature.update((byte) nextByte); // also update // calculated // one pass // signature // result.append((char) nextByte); // add to file instead of StringBuffer targetStream.write((char) nextByte); } targetStream.close(); } else { throw new RuntimeException("unexpected message type " + message.getClass().getName()); } if (calculatedSignature != null) { PGPSignatureList signatureList = (PGPSignatureList) objectFactory.nextObject(); System.out.println("signature list (" + signatureList.size() + " sigs) is " + signatureList); PGPSignature messageSignature = (PGPSignature) signatureList.get(0); System.out.println("verification signature is " + messageSignature); if (!calculatedSignature.verify(messageSignature)) { throw new RuntimeException("signature verification failed"); } } if (encryptedData.isIntegrityProtected()) { if (encryptedData.verify()) { System.out.println("message integrity protection verification succeeded"); } else { throw new RuntimeException("message failed integrity check"); } } else { System.out.println("message not integrity protected"); } //close streams clearDataInputStream.close(); } } Cheers, B. --- ## CF: New version of BonCode PGP library released URL: https://www.boncode.net/cf-new-version-of-boncode-pgp-library Date: 2011-12-26 I had a few request to look into the PGP library I released for ColdFusion and Railo last year. It took me a while to understand my own code, then, a while longer to implement the features that I wanted to add ;o) The main add on this time is the ability to create single pass signed files. This allows you to create a file where you are assured that only the authorized receiver can read them, while the receiver is assured that the sender is authentic as well.  Yep, I know sound like cold-war stuff, but it is quite common scenario in financial exchanges to assure both sides that everything is the way it should be. To a lesser level some other additions and bug fixes were completed as well. All this, as usual is open source. You can download code, examples, and implementation from here: https://github.com/Bilal-S/cfpgp/releases/tag/2.0.0 Best, B. --- ## CF: Setting up the OWASP ESAPI Library for use with ColdFusion and Railo URL: https://www.boncode.net/cf-setting-up-owasp-esapi-library-for Date: 2011-12-20 If you are taking application security seriously or have been curious about it you know by now that the native tools built into ColdFusion and Railo are not sufficient to hinder the serious hacker from making headway. To truly use best practices you can do a lot of code development, or, fall back to a project that has already proven its merit through many years of practical use. I am referring to the OWASP Enterprise Security API (ESAPI). Unfortunately, getting this puppy running in any shape requires some reading muscle and some luck and some powers of deduction. I am summarizing here the findings, so you don't have to run through the maze of options and boiling it down to something simple. First, you will have to download the jar file (as of this writing it would be esapi-2.0.1). The download is around 14MB but you only need the esapi-2.0.1.jar file. Copy the jar file to (backup any esapi file that already exists in there first): [cfroot]/wwwroot/WEB-INF/lib in Adobe Coldfusion. WEB-INF/lib in Railo Then, download a good ESAPI.properties file. Most of my head banging and hair ripping surrounds finding the property definitions. Can't stress this enough. Start with the one from source code it has good comments. Go through this file carefully and make needed changes. Make sure all directories referenced in the properties file actually exist on your drive system and also change default Encryptor.MasterKey and Encryptor.MasterSalt to something you are comfortable with, e.g. do not use something like this: Encryptor.MasterKey=changeme Encryptor.MasterSalt=blah After you made changes save it (e.g. c:\esapi\files). Thirdly, make environment start up changes. If you are using Adobe Coldfusion you will need to change the JVM startup properties in CF Administrator to add a property and point to place where you placed ESAPI.properties file. E.g.: -D org.owasp.esapi.resources=c:\esapi\files For Railo, the above is done in Tomcat/Jetty startup parameters. Fourthly, change classpath (Yep, you heard right change JAVA classpath): Add the directory you placed the properties file in to Java classpath. This is something that had me stumped as well. After all of the above, give your server a good schake (restart), and then test whether all works. Simple code snippet: <cfset esapi = CreateObject("java","org.owasp.esapi.ESAPI")> <cfset encoder = esapi.encoder()> <cfoutput> <cfset myInput="<script>some input for html context; alert('doing something you don't want');</script>"> #now()# <br/> #encoder.encodeForHTML(JavaCast("string", myInput))# </cfoutput> The good news is that Adobe is looking into bundling this in the future so you don't have to. However, in the meantime this is good practice ;o) Best, B. --- ## Internet Explorer and the case of the vanishing Forms URL: https://www.boncode.net/internet-explorer-and-case-of-vanishing Date: 2011-12-08 So we ran into the problem of a customer's users' not being able to use our application. The users happen to use Internet Explorer and IIS (Internet Information Server) and the behavior was intermittend. We thought, this is a network issues for sure; so we put sniffers on client and servers sides and observed that nothing was conclusive. Another thing that threw us was that using an alternate browser such as Chrome everything seemed to be working. When things did not work, however, we saw that IE (version 6 through 9) would not send any HTTP form information along. So even with simple HTML page that had two form fields "FirstName" and "LastName", we would see through the protocol capture that IE started an HTTP post, but no form fields and values. They had vanished. Poof ! Our further suspicion of maybe a plugin, proxy or firewall stripping this data out was also eliminated and we started staring at each like we are all going crazy. And, of course, we googled. Nothing there either. (Google, oh Google, why did you fail us!)... Then, a little break, we discovered, that everytime things stopped working and Forms started vanishing, the user had just entered a secured area of the site and returned to an unsecured area. The security access was transparent as IIS was setup to use "Windows Authentication" similar to "Integrated Authentication"; thus, IE was doing this in the background. Thereafter, even if the user returned to the non-secure areas of the site, IE would refuse to send Form data. After more digging we found that this seems to be intentional; we even found an old web-page that descibed this as good feature for IE6. The behavior is this: after, IE authenticates to a site via NTML / Kerberos (i.e. some integrated way), all traffic to that site has to be secured and as part of the security mechanism no plain text form submission is allowed. Great ! The solution to this was to move the secure portions to a seperate site on IIS and thus everything started working as it should. IE was happy, customer was happy, and we could go to sleep. Hope you don't have to spent as much time on troubleshooting knowing this. B. --- ## CF: Tracing AMF (Action Message Format) packages for Flex/BlazeDS in Coldfusion URL: https://www.boncode.net/cf-tracing-amf-action-message-format Date: 2011-11-23 I know I had seen this and done this before but for some reason I could not find it. I am looking at a Flex based component that makes remote calls to ColdFusion (Flash Remoting), then, renders some of the data. Now I wanted to find out what is happening and more specifically what data is being exchanged between Flex and ColdFusion. As you might know, the exchange between CF and Flex is in AMF format, which is a binary format and thus not easily readable over protocol sniffer. I know, I know, I can get many tools, and ServiceCapture is mentioned many times; but I wanted to do this simpler. What I done in the past is used the command window to get this, but with many things, you forget, or just get older ;o) So you can start ColdFusion in a Command / Terminal window, by going to the installation folder and finding the right startup script. For windows: [cfroot]\bin\cfstart.bat This will start the ColdFusion server in command window: Command Window running ColdFusion However, this did not automatically decode the AMF messages or gave me insight into flash remoting. In order to that I had to find the flex services-config file. On stand-alone server install on Windows this would be located here: [cfroot]\wwwroot\WEB-INF\flex\services-config.xml find the logging section and change logging level to "Debug" like so: <logging> <target class="flex.messaging.log.ConsoleTarget" level="Debug"> ... </logging> You can even change the prefix of the messages, e.g. to Flex like so: <logging> <target class="flex.messaging.log.ConsoleTarget" level="Debug"> <properties> <prefix>[Flex] </prefix> This is the cheap way of getting debugging going on the protocol and see what is being exchanged. Hope this helps, -B --- ## CF: CFCamp 2011 presentation and sample code URL: https://www.boncode.net/cf-cfcamp-2011-presentation-and-sample Date: 2011-10-29 A long day at CFCamp came to a social conclusion at the Marriott-bar. This again confirms the impression that the ColdFusion community is approachable by old and new hands alike. Another interesting fact about the CF community emerged. According to the custodial support staff, the CFCamp attendees consumed three times as much coffee as crowds of a similar size. Definitively a mark of distinction. Thanks to the organizers, presenters, and attendees for making this a solid CF event. Overall, learned new things from all and had a Pretzel to boot. As discussed, I posted the the presentation slides and sample code for download. Cheers, B. --- ## CF: Munich in the Fall, CFCamp 2011 URL: https://www.boncode.net/cf-munich-in-fall-cfcamp-2011 Date: 2011-10-14 So, you just missed Oktoberfest and were wondering what else there is to do in Munich in the Fall. Well, you happen to be in luck, especially if you are a ColdFusion enthusiast. It so happens that this year a few fellow believers in the art of the Pretzel and motivated ColdFusion learners are assembling on October 28th for CFCamp 2011. Even yours truly will make the trek down  to Bavaria's Capital to chat and learn from others. Will also do a talk on application security, sharing some nuggets of the school of hard knocks etc. As far as I understand it, it is not too late to signup and the Beer and Pretzels are beckoning.... Cheers, B --- ## .NET: wddx.net library revision URL: https://www.boncode.net/net-wddxnet-library-revision Date: 2011-10-09 Before web services, before JSON, before many other things or people ever thought about it,  there was this other way to exchange data across platforms via the Internet using XML. It was called WDDX (Web Distributed Data Exchange). According to Wikipedia this its definition: WDDX (Web Distributed Data eXchange) is a programming-language-, platform- and transport-neutral data interchange mechanism to pass data between different environments and different computers. It supports simple data types such as number, string, boolean, etc., and complex aggregates of these in forms such as structures, arrays and recordsets (row/column data, typically coming from database queries). Support for WDDX is available natively in several languages including ColdFusion, PHP, Ruby, and Python. Other languages implement this through add ons. .NET belongs to the later category, thus needs a library to process WDDX. Unfortunately, this library has not seen updates in a long while. It is open source and was created by Joel Mueller early in the 2000s and not much happened since then. First, Kudos for Joel taking on this project and making it available. It is well documented and executed; unfortunately, as with any software, there were some issues. Having discovered these and "fixed" them, the question of getting the fixes back into distribution came up. After several attempts to contact the current maintainer of this project and several months of wait time I got very frustrated and decided to take over some of this. Rather than branching this on Microsoft Codeplex site (this is Microsoft's site for maintaining open source projects) I used Git Hub. The main reason for me to use another site for maintenance was that Codeplex seem to not get any attention from Microsoft. Bug messages were being ignored, documentation did not match to what the site did or operated. Download WDDX.NET library: https://github.com/Bilal-S/WDDX.net So I hope that if you need WDDX support in .NET you will check out this project. As usual please let me know if you find any issues. Best, B. --- ## NCDevCon: Presentation Slides and Code URL: https://www.boncode.net/ncdevcon-presentation-slides-and-code Date: 2011-09-18 The NCDevCon 2011 conference is on its way to be concluded. Many interesting and well rounded presentations. Meeting friends from all over again and chatting about the best and worst way of doing things. I am continuing to be impressed what the team (Dan Wilson, Jim Priest, Shawn Dunning) is able to do with so little resources. Way to go team. As promised I am posting the links to the slides to my presentations: Practical Application Security: Practical Application Security Slides I posted the code for URLEncoder on RIAforge as open source project. Client Side MVC with Sencha Touch: Client Side MVC with Sencha Touch Slides Download Sencha MVC code. Please review the Readme_first.txt file on how to get this going. Please feel free to explore code and slides. The conference also posts the video of the presentations. Cheers,  -B. --- ## CF: Using URLEncoder to secure URL Parameter against CSRF and XSS URL: https://www.boncode.net/cf-using-urlencoder-to-secure-url Date: 2011-09-18 In my presentation about ColdFusion Application Security I also showed a reference implementation of an URLEncoder that can assist with three scenarios: Cross Site Scripting: If scripts are injected through URL parameters, this encoder will ensure that no user inputs besides the one set by CF are accepted. Insecure Direct Object Reference: By encrypting the object references in passed URL the object reference are no longer exposed to users and cannot be changed by users. Cross Site Request Forgery: By adding additional reference in the encrypted packages the URLEncoder will assist with Cross Site Request forgery attempts. The URLEncoder allows a very flexible way of transporting data via URL parameters in a secure fashion. It is not restricted to primitive/simple data types. Complex data such as arrays and structures can easily passed  via the URL using this component as well. Moreover, additional security option are available. During encoding, you can specify whether the generated URL has an expiration and or can only be used from the originating URL. During the decoding phase the URLEncoder you can specify which scope the transported data from the URL parameters will be placed in. By default this will be placed into Request.URL, however, you can change this to be placed into the regular URL scope so that legacy application will only need minimal change to add this layer of security. Here is the link to the download to the project from RIA Forge. Cheers, -B. --- ## NCDevCon 2011: Developer Conference coming up Setp 17-18, Raleigh, NC URL: https://www.boncode.net/ncdevcon-2011-developer-conference Date: 2011-08-31 For the last three years an amazing thing has happened. The Triangle Area ColdFusion User's Group (TACFUG), has put a lot of blood, sweat and tears into organizing a conference, NCDevCon, that has ColdFusion at its center. This by itself is an amazing feat; especially given that the large ColdFusion specific conferences are faltering and Adobe, the main source of CF, does not have an independent gathering focused on this topic. On top of this, the conference manages to have broad coverage of many relevant areas of Colfusion and Web development while also giving beginners options for hands on sessions. This is a major, major (yes two majors!) achievement. So definetly cudos to the organizers. All this is available for a very small fee ($60) compared to the several hundreds of dollards we commonly pay. So definetly a deal in light of the knowledge that is being shared. I have been selected to do two presentations this year on very different topics. The first one on Application Security, I can see eyes already glazing over, nope we'll provide some practical code here as well. The other one is on mobile application developement with Sencha Touch and ColdFusion. This one is harder to organize as I have lots of material I am trying to decide what to cut out at the moment. Hope to see you there. Cheers, -B --- ## CF: Decide if we got enough memory to succeed URL: https://www.boncode.net/cf-decide-if-we-got-enough-memory-to Date: 2011-08-24 Since the beginning of computing there has been the struggle between available resources and the number of computing tasks to run on them. When we had 16KB of RAM our code looked very compact and we were critical of any extra bytes that we stored or computing cycles we ran. When, today, we easily reach 16GB of RAM the level of individual byte analysis does not quite happen. More likely than not, we tend to worry less about do we have enough memory to run this operation and assume (to our chagrin) that things will work themselves out,... right until they don't. Which brings me to the problem at hand. Rather than running a process, thread, task and hoping things work, can we predictably make that decision instead? In my case, this being ColdFusion I needed to find out whether I had a snowballs change in the Hot-Place to open an Excel file. Remember that ColdFusion uses the Apache POI library to read Microsoft Office documents. Works normally fairly transparently but the downfall here (it is documented as well, see POI docs) is that POI will grab big chunks of memory for processing any access to, say, a spreadsheet. This, if not managed, gets us into an unconfortable situation of crashing the server with OutOfMemroy exceptions. Yep, not good. So our solution was first determine a common estimation factor (spreadsheet size to JVM memory size), then use it to see whether we would have a chance of opening / loading this spreadsheet at all given the current memory envelope on the server. Nice message to user if we had no chance, go ahead and process otherwise. This eliminates unneccesary server crashes. Which is, indeed, a very good thing. Here is the code snippet we used to determine available CF server memory: <cffunction name="getMemory" returntype="numeric" access="private" hint="return server unused available memory"> <cfscript> var intMB = 1024 * 1024; var objRuntime = createObject("java", "java.lang.Runtime").getRuntime(); var intUsedMem = objRuntime.totalMemory() - objRuntime.freeMemory(); var intAvailableMem = objRuntime.maxMemory() - intUsedMem; return (intAvailableMem/intMB); </cfscript> </cffunction> The value here will have to be compared against the expected value of memory use for your operation. For example, if you expect your spreadsheet to occupy 100MB memory while loaded into JVM and want to have a margin on 50MB, you can only proceed with the operation if the return of the above function is a value of 150 or greater. Cheers, B. --- ## Facebook and Automatic Granting of Permissions to Applications via Mobile Devices URL: https://www.boncode.net/facebook-and-automatic-applications Date: 2011-08-19 I make it a policy of conduct not to install any Facebook application or grant any Facebook apps rights to my Facebook account. Call me paranoid (many have). So, needless to say, I was surprised when I was looking at my settings page under application how many applications I seem to have granted access. There they were, a little more than half a dozen apps that seem to have access to my information and friends, not remembering, having granted any of them the right to do so. This baffled me to no end. How did this happen? Well, the only thing that seemed to be a common pattern for these apps is that I had loaded similarly named application on my iPhone from the Appstore. Ahh, yes, here is where the plot thickens. Thus the best I can explain this is that the terms of acceptance of these apps includes that they can access my Facebook profile. Thus, if they detect the Facebook app loaded on your device they establish connection and register themselves as authorized apps with Facebook. I might get this all completely wrong, but this is the only explanation I can come up with, since I got this policy of no apps etc. Yes, some of you may now say that I was too trusting a soul, and this, too, might be true, so I am now checking more regularly to see whether I am being hoodwinked into approving this type of behavior. I am now checking regularly what the Facebook app settings page looks like (see below) and killing the permissions. I truly wish that FB had explicit lock on this type of stuff as this is very sneaky behavior in my opinion. As usual would appreciate some feedback. Cheers, -B. --- ## CF: ColdFusion Debug trace for remoting (Flex, SOAP, anything else) URL: https://www.boncode.net/cf-coldfusion-debug-trace-for-remoting Date: 2011-07-28 One of the things I have always liked with working in ColdFusion is the ability to derive detailed debugging information. You get a good idea of what is going behind the covers and do have a good basis to hunt down bugs.Unfortunatly, this all breaks down when you start to do any kind of remoting (invoking CFCs from another technology). Currently, this is for Flex and SOAP (Webservices) type calls. If anything goes haywire, or the calls themselves are complex, e.g. call on many other components and tags you fly in the dark more often then not.The common response to this kind of issue from peers is to use the line debugger, set breakpoints etc. and this does work to a certain degree.However, where I get a little agitated is that most of the time when problems occur you are nowhere near a line-debugger or IDE to capture the processing.For standard .cfm pages I can use the Silent Debugger option.So I was wondering if I could build something similar that worked with CFCs and remoting. I would add this to the Application.cfc and, bingo, I could capture the debugging output to file. Alas, many hours later I had nothing workable. To make a long story short it does not look like there is a way to capture cfc debug output, because no debugging session is seems running.Unfortunatly, it looks like the auto-wiring that ColdFusion performs makes the decision not to initialize / start a degugging session in the ServiceFactory (coldfusion.server.ServiceFactory).Thus the call for factory.getDebuggingService() will fail and my attempts to manualy start the debugging service failed for lack of insight into how CF actually does this (what classes and method in what order).So I was back to square one.After a little more thinking and tinkering I decided to go for the workaround solution. This happens to be practical enough for me as my remoted cfcs are only stubs, so not much functionality is implemented there.I have several stub types and, thus, decided to rewrite the call from SOAP / FLEX remoted calls to HTTP Post (REST) calls.So in the remoted call I would just turnaround and call the REST gateway if I detected that we were trying to debug stuff using the IsDebugMode() function.This would allow me to use the Silent Debugging option and capture the debug output to file even for calls coming from SOAP and FLEX remoting. I would also need to translate the reponse back correctly for FLEX and SOAP clients to consume.All this is more overhead but not drastically so, while allowing me to trace errors while they occur even for remoted CFCs. I can access this information afterwards for analysis.Overall, I am disapointed that I was not able to hook into native CF processes to expose debugging results. Maybe in future iterations this will be possible. However, being able to get this insight is invaluable to me.Feel free to experiment.Cheers,B. --- ## CF: cfObjective 2011 URL: https://www.boncode.net/cf-cfobjective-2011 Date: 2011-07-21 Meant to provide feedback on the cfObjective conference in Mineapolis, MN.The conference goes by the tagline of"The Only Enterprise ColdFusion Conference". Unfortunatly, this may be very true.Anyways, here is the skinny as I see it (fully my opinion):Even though this is the biggest CF conference that still is around, I was still disappointed by how small the crowd was. No knock on this conference as it comparitively has grown from last year, but with the demise of cfUnited, I was expecting a larger crowd to carry over to this one.Conversations with fellow conference attendees lead to the insight that instead of one big conference there are many smaller regional ones that focus on this topic.If this is the trend, the obvious question would be how CF is CF going to survive? Will many small conferences attract developers by the truck load or will they stay away? Adobe did not sponsor, I hear lots of politics involved. Not a good image if you are trying to convince new people to pick up CF and grow the community.The location was OK. Downtown Minneapolis is not hot but you can make it work. Weather was a bummer (pretty nippy). The food was good, lunch was better than breakfast.The presentations followed a similar pattern to cfUnited, the same people are doing the presenting. The quality was just a notch above what was available at cfUnited. I am personally getting a little tired of the same presenters, I think the community needs some fresh blood. Only so many times I can hear an extreme opinion presented as fact ;o)Overall, still something I will attend, but maybe shorten the time for next year. Do only two days rather than three. The last day was just a rush to get out.There you have it. Catching up on writing.B. --- ## CF: Coldfusion java.lang.StackOverflowError URL: https://www.boncode.net/cf-coldfusion-javalangstackoverflowerro Date: 2011-04-21 If you run into this with ColdFusion, it probably will appear to come out of no-where.One day everything will work fine and, the next, without any change you can think of, you see your site stop to respond.Upon digging into the exception.log file you see something like this:"Error","jrpp-0","04/20/10","17:33:53",,"'' The specific sequence of files included or processed is: C:\Webroot\Test4\TestFile.cfm'' "java.lang.StackOverflowError at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2263)This for me occurred when serializing/de-serializing data. But anytime you run into this you have to ask yourself one primary question.Did this happen because of my logic? If yes, go revise your logic first.If you are certain your stuff is solid, you need to increase the Stack Size by providing the -Xss directive to the jvm upon ColdFusion startup.I would bump it four fold; while the default seems to be slightly different based on OS, it is normally in the 300-400kb range.I bumped mine up first to 10MB, then, reduced it to find out exactly what was workable.The -Xss argument can be specified in kb e.g. -Xss512k or in mb, e.g. -Xss1m.here is an image with configured jvm:Cheers,B. --- ## inno: converting Ansi string to string URL: https://www.boncode.net/inno-converting-ansi-string-to-string Date: 2011-04-01 When you work in Unicode Inno Setup the data typing of strings for functions seems to always get you one way or the other.There are no easy build in conversions either.After running into this repeatdly I build a helper function that simply converts the Ansi string to regulare string.May come in handy for others://convert Ansi String to Stringfunction ConvertToString(AString:AnsiString):String;var i : Integer; iChar : Integer; outString : String;begin outString :=''; for i := 1 to Length(AString) do begin iChar := Ord(AString[i]); //get int value outString := outString + Chr(iChar); end; Result := outString;end;Cheers,B. --- ## tomcat: Another way to connect IIS and Tomcat URL: https://www.boncode.net/tomcat-another-way-to-connect-iis-and Date: 2011-03-23 If you were working with tomcat and IIS for a while you know things are getting a little long in the tooth. The last principle update to how IIS and Tomcat interact was made in early 2000. In the meantime many changes have occured to IIS and Tomcat with more capabilities added. So, I thought it would be time to also update the way IIS and Tomcat connect. I just published a project on RIAForge whose goal is to modernize this part: Lastest Release Available on Github. Online Documentation is regularly updated. Here are some reasons to consider a new connector: • no ISAPI code • no IIS6 vestiges or backward compatibility elements needed on IIS7 • all managed code using the modern extensibility framework • works on IIS6 and IIS7 • speed improvements • easier control by file type on IIS side • no virtual directories and virtual mapping needed • configuration can be inherited to sub-sites and virtual sites • easy install/uninstall • support partial stream sending to browser (automatic flushing) with faster response to client • support both 32/64 bit of Windows with same process and files • transfer of all request headers to servlet container • build in simple-security for web-administration pages Happy experimenting, B. --- ## .NET: C# find pattern in byte array URL: https://www.boncode.net/net-c-find-pattern-in-byte-array Date: 2011-02-24 Byte Arrays are not as easily handled as strings when it comes to finding what they contain, especially if we are searching for a pattern of matching bytes.It seems like everyone is rolling their own on this one. Most examples I have seen look at converting bytes to strings and then using IndexOf operators.However, if you use bytes that cannot be converted to a string easily or do not want to use string comparison here is my version of a working function that does the trick.private static int ByteSearch(byte[] searchIn, byte[] searchBytes, int start = 0){ int found = -1; bool matched = false; //only look at this if we have a populated search array and search bytes with a sensible start if (searchIn.Length > 0 && searchBytes.Length > 0 && start <= (searchIn.Length - searchBytes.Length) && searchIn.Length >= searchBytes.Length) { //iterate through the array to be searched for (int i = start; i <= searchIn.Length - searchBytes.Length; i++) { //if the start bytes match we will start comparing all other bytes if (searchIn[i] == searchBytes[0]) { if (searchIn.Length > 1) { //multiple bytes to be searched we have to compare byte by byte matched = true; for (int y = 1; y <= searchBytes.Length - 1; y++) { if (searchIn[i + y] != searchBytes[y]) { matched = false; break; } } //everything matched up if (matched) { found = i; break; } } else { //search byte is only one bit nothing else to do found = i; break; //stop the loop } } } } return found;}Cheers,B. --- ## CF: ColdFusion Report Builder migration errors with Invalid construct.A script statement must end with “;” URL: https://www.boncode.net/cf-coldfusion-report-builder-migration Date: 2011-02-08 You may had the opportunity to work with ColdFusion Report Builder in the past. It was a cool little tool that we used with ColdFusion 7 when you could not afford anything else to write reports with.In its first iteration it was pretty buggy; today, it still is around but I see fewer people using or mentioning it. It barely gets any play at the user conferences and is treated more like a red-headed step child (I have nothing against red headed people of any kind ;o).In my opinion it is still a useful tool that does not get its share of attention. However, when you migrate from older versions of reports that you have written with, say, ColdFusion Report Builder (CFRB) 7, to ColdFusion Report Builder 8 or 9 you may get some fairly unexpected errors.Such as this:Invalid construct.A script statement must end with ";"The only thing you did it just open and save the report. No changes were actually made. All of a sudden, errors jump up from seemingly nowhere. Well, for me, that resulted in many hours of ghost hunting (since I cannot see what's in the cfr files) until I finally got the bright idea to dig up an old copy of Report Writer 7 for those reports.I restored the .cfr file from backup, made a change using CFRB 7 and everything worked. Just to check for sanity, I, then, restored the file again, made a simple change using either CFRB 8 or 9 and, boom, broken again.The lesson here is to make sure you ask before you touch a ColdFusion report (.cfr) file with which version of ColdFusion/ColdFusion Report Builder it was created. Then, make the modifications only with that tool.This in the end may save you many hours of frustration.Cheers,B. --- ## CF: Explicit “undefined” in ColdFusion 9 results in Bug when using CustomTag Attribute collections URL: https://www.boncode.net/cf-explicit-undefined-in-coldfusion-9 Date: 2011-01-10 Adobe ColdFusion 9 introduced many new enhancements but as with any major release there are new behaviors and new problems galore.This particular bug I encountered deals with a change in behavior of component function processing. I encountered this while migrating an application from CF8 to CF9.In previous releases of ColdFusion an Argument that was not passed would not exist in the arguments scope. With ColdFusion 9, an argument is always created even if not passed if it is part of the arguments declaration in your function.For example this simple function:<cffunction name="fTwo"> <cfargument name="argA" default="1"> <cfargument name="argB" required="no"> <cfreturn arguments></cffunction>a dump of this function will return:1: <cfdump var="#fTwo()#">2: ARGA 1ARGB undefinedRather than justARGA 1Thus ColdFusion 9 is introducing a new state in the variables, the Explicit "undefined".Since this is a new state all function working with CF objects/ i.e. variables will also need to be aware of it. And most are and, thus, little problem.However, if you introduce some slight alterations, e.g. call a custom tag from a component, this system fails.You will get errors as the IsDefined() function will identify something as defined while it is not.Let's introduce a simple custom tag (CT9Test) with the following 6 lines of code:1: <cfdump var="#Attributes#">2: <cfif IsDefined("Attributes.ArgB")> 3: Attributes B is defined4: <cfelse> 5: Attributes B is NOT Defined6: </cfif>7: 8: First let's call this custom tag from the function like so:1: <cffunction name="fTwo"> 2: <cfargument name="argA" default="1"> 3: <cfargument name="argB" required="no"> 4: <cf_CT9Test attributeCollection = "#Arguments#">5: </cffunction>6: Nope. This is still good. No problem here. But, let's go ahead and break ColdFusion:1: <cffunction name="fThree"> 2: <cfargument name="argA" default="1"> 3: <cfargument name="argB" required="no"> 4: <cf_CT9Test anotherVar="something" attributeCollection = "#Arguments#">5: </cffunction>6: You see the difference?We are simply adding another parameter to be passed to the custom tag in addition to the attribute collection received from the function arguments.In the above case, the attributes.argB all of a sudden becomes defined. But since it is explicitly "undefined" using it will throw weird errors.Something like:if (IsDefined("attributes.argB") ) calc=attributes.argB + 1;will fail.The workaround to this is to go back to scenario one and not use any additional parameters when calling your custom tags and using attributeCollection. Package all parameters into one structure, e.g.1: <cffunction name="fFour"> 2: <cfargument name="argA" default="1"> 3: <cfargument name="argB" required="no"> 4: <cfset arguments.anotherVar="something">5: <cf_CT9Test attributeCollection = "#Arguments#">6: </cffunction>7: Now that you know this. Happy migrating.-B --- ## CF: Railo 3.2 Released URL: https://www.boncode.net/cf-railo-32-released Date: 2010-12-29 After much work the Railo team released the new version (3.2) of Railo over Christmas.Railo is one of the Open Source ColdFusion application engines available. The other notable one is Open Blue Dragon.If you are doing ColdFusion based programming this is something that should belong to your stable of tools that you are familiar with.In the past the discover-ability of Railo was harder as it was not as easy to understand how to get things going once you downloaded it. Though technically simply the step of getting it installed and going was a hurdle that made it harder than the Adobe engine.With this release among a myriad of enhancement installers were made available for multiple platforms. For example, for the windows platform the comparable Railo installer is one third the size of Adobe's while it handles both 32 and 64 bit installations.Happy Experimenting,B. --- ## XJS: Using the debugger command to start a debugging session URL: https://www.boncode.net/xjs-using-debugger-command-to-start Date: 2010-12-01 The ability to kick of the an in-line step-by-step debugger was introduced in JavaScript early on. Since before JS version 1.5, I believe. However, practically speaking there were few client-side debuggers that could take advantage of this.Thus, the use of it has not been heavy even after the more ready availability of Browser development support and in-line debuggers. Today, all browsers support some sort of step-by-step debugger that can be used in concert with the debugger command to more effectively debug code, so perfect time to remind us of this option.Why would we need to use it?. Let use this snippet as an example:for (var i=0; i <= 10000; i++) { if (i==98) { debugger; } }Using conventional in-line debugging you would have to set a break-point, then iterate along until you reached the loop condition that you were interested in, i.e. 98. Using the debugger statement, you simplify this drastically.Expanding this principle into use with ExtJS is easy. Giving the nested nature of much of the ExtJS code and heavy use of complex configuration objects setting breakpoints is sometimes a game of hit-and-miss.Using the debbuger statement you will still able to halt the execution at the right place even if you did not hit the correct break-point in your debugging tool.For example: 1: listeners: { 2: render: { 3: fn: function(){ 4: //stop for debugging here 5: debugger; 6: 7: Ext.fly(clock.getEl().parent()).addClass('x-status-text-panel').createChild({cls:'spacer'}); 8: 9: //Kick off the clock timer that updates the clock el every second:10: //Would need to be set in application format11: Ext.TaskMgr.start({12: run: function(){13: Ext.fly(clock.getEl()).update(new Date().format('g:i:s A'));14: },15: interval: 100016: });17: },18: delay: 10019: }20: } Here we can stop when then rendering is activated to investigate code execution further.The debugger statment works in most browsers, i.e. Firefox with Firebug, IE 8, Chrome. In IE you will have to explicitly put the browser in debugging mode by clicking the "Start Debugging" button in the developer tools.Happy Debugging,B. --- ## XJS: Avoiding of Anonymous Functions Example URL: https://www.boncode.net/xjs-avoiding-of-anonymous-functions Date: 2010-11-20 One of the difficulties one faces quickly using the ExtJS framework is the code organization. Any project quickly grows into a jungle of anonymous functions and heavily nested configuration objects. Hard to read and hard to maintain.Examples commonly start simple but as soon as more elements are added they turn off newbies. A configuration object spanning multiple screens is not easy to digest, but this is how most online examples are presented. This, according to my informal survey, discourages new developers from proceeding.This, in my opinion, is one of the greater roadblocks to learning the framework and making scalable ExtJS apps. I understand that changes in ExtJS 4 will introduce a more mature MVC based application framework; however, the examples I have seen are still heavily reliant on multi-level nesting and anonymous functions.It is of course, a matter of preference, but I do find organizing code written in that fashion harder to read and manage long term.For once, common mistakes, such as missing a semicolon, comma, or bracket closure, result in disproportionate debugging time. On the other hand, having multiple team members working in their own "sandbox" is hard to do if everyone is trying to change the same file.Thus, I was looking for alternate organization but could not find a simple example to show that another approach was possible.Take this common ExtJS code as example (this is a fairly simple example in ExtJS realm). It draws a border layout based viewport:Ext.onReady(function(){ new Ext.Viewport({ layout: 'border', items: [{ region: 'north', html: '<h1 class="x-panel-header">Page Title</h1>', autoHeight: true, border: false, margins: '0 0 5 0' }, { region: 'west', collapsible: true, title: 'Navigation', width: 200 // the west region might typically utilize a TreePanel or a Panel with Accordion layout }, { region: 'south', title: 'Title for South Panel', collapsible: true, html: 'Information goes here', id: 'southPanel', split: true, height: 100, minHeight: 100 }, { region: 'east', title: 'Title for the Grid Panel', collapsible: true, split: true, width: 200, xtype: 'box' // more nested code could be added here, e.g a GridPanel }, { region: 'center', xtype: 'tabpanel', // TabPanel itself has no title items: { title: 'Default Tab', html: 'Tab conent' } }] }); });'The formatting is nicely done, but still requires some getting used to. Only a few nested elements in this one yet the complexity can be already seen. What if you had a team of developers each working on one of the panels?I prefer a more verbose but easier maintainable format that achieves the same result while allowing easier developer task separation (the use of multiple script tag is optional, I wanted to show a sense of separation of code):<script type="text/javascript"> //we define a namespace to use for organization. This is optional. Ext.namespace('startup');</script><!-- panel definitions could be in another file --><script type="text/javascript"> // each panel could be seperate script file maintained by seperate developer or dynamically included via // app server such as PHP / Railo / etc. startup.northpanel = { region: 'north', html: '<h1 class="x-panel-header">Page Title</h1>', autoHeight: true, border: false, margins: '0 0 5 0' }; startup.westpanel = { region: 'west', collapsible: true, title: 'Navigation', width: 200 }; startup.southpanel = { region: 'south', title: 'Title for South Panel', collapsible: true, html: 'Information goes here', id: 'southPanel', split: true, height: 100, minHeight: 100 }; startup.centerpanel = { region: 'center', xtype: 'tabpanel', // TabPanel itself has no title items: { title: 'Default Tab', html: 'Tab Conent.' } }; //assemble panels here into array, alternatly this array could be the items definition startup.aItems = [startup.northpanel,startup.westpanel,startup.southpanel,startup.centerpanel];</script><script type="text/javascript"> startup.DoInit = function () { //create view port var bport = new Ext.Viewport({ layout: 'border', items: startup.aItems }); }</script> <script type="text/javascript"> //the actual ExtJS onReady function remains very small Ext.onReady(function(){ startup.DoInit(); }); //end onReady</script>Of course, there is the element of preference and argument about throw away functions, e.g. only run once; I would still prefer good naming and definition as this is the long run makes my life easier.Feel free to comment.Cheers,-B --- ## XJS: Sencha 2010 con impressions URL: https://www.boncode.net/xjs-sencha-2010-con-impressions Date: 2010-11-16 I am attenting the Sencha (formerly ExtJS) developer conference to learn about the future. Overall good energy at this conference. Definite feel of excitement about product and company from the developer community. Here are some early impressions:Lots of activity since the company got fundingCompany is trying to grow up and it shows: products are beeing build out, revenue model is being decided on / experimented with, business processes look raw around the edges. Overall this puppy is growing up.Sencha has many projects in the cooking pot with some very innovative ones in the mix while still putting good improvements into the existing ones. The question will be, is the company going to be able to pull all this off or are they overloaded. Deliveries could slip, quality could suffer etc.Their bread and butter ExtJS 4 is getting a dose of good overwhaul inlcluding things I have been griping about for a while. The main thing for me is that a best practices application structure is now supported out of the box, so you can finally organize your code for larger apps in a meaningfull way. (Yeah!!!) . My impression is that there are still some challenges to overcome with backward compatibility which they are working on. Many more good things of course, hope they can pull it off.The developer interest is increasing, 3 x the number of developers attended this year.Keynote from at&t cto John Donovan (he loves all phones and all people, yeah very politically correct answers all the way). The nugget from him was the statement that HTML5 is a viable application plattform and mobile apps will be written in it more the future and at&t will support it on many devices with native device library connections. If you believe this, the future of Flash and Flex would look limited. Another conference attendee said "Adobe is the dead man walking". Wow!The Sensha touch platform for mobile apps is going to be free. Cool.Common Annoyance: "It works in webkit" myopia. Understandably browsers supporting HTML5 are cooler from developer perspective but many examples given did not work or broke when another browser was used (Firefox, IE). This is poor for any platform claiming universal compatibility. Hopefully this will improve next year.Cheers,-B --- ## CF: ORM EntityDelete without EntityLoad URL: https://www.boncode.net/cf-orm-entitydelete-without-entityload Date: 2010-09-30 I must admit I am not a fan of the EntityDelete() function. Its inability to handle multiple records always nagged me. I know I can allways go back to CFQUERY or use ormexecutequery(). But what nagged me the most appeared to be the need to do an EntityLoad before I could remove the entity/record. This could potentially introduce unneeded database reads and latency.e.g.: myBook = EntityLoad("Book", 100, true); EntityDelete(myBook);Well it turnes out that the use of EntityLoad is not required. A colleague suggested I try the following instead which would eliminate the load operation, and since I thought that was pretty neat I am sharing ;o) mybook = new Book(); mybook.setBOOKID(100); EntityDelete(mybook);In this fashion, you are creating the object reference in memory and guaranteeing that there is only one DB interaction at DELETE.Cheers,Bilal --- ## VS2010: Visual Studio 2010 – finding web reference option when working with Windows Forms Applications URL: https://www.boncode.net/vs2010-visual-studio-2010-finding-web Date: 2010-07-25 Something I ran into today made me do a double take. This could have originated from the initial configuration choice I made when setting up Visual Studio 2010 or the tool is trying to be so smart it starts to get confusing..However it happened, it does seem to make things more difficult when trying to create windows form applications. In particular, if you want to use a web-reference in your regular windows application the number of clicks has increased and discoverability has decreased.Adding web-references to consume web services in ASP.NET application is not impacted by this change. In particular the context sensitive links to add web-reference are gone when I am in the Solution Explorer working on a Windows Form Application.Instead the only thing you can seemingly do is to add a service reference. Though you can start here, web services that are registered through this channel do not behave at all like the previous releases of Visual Studio. Thus, beware, this is not what you want to do if you want to consume a regular web service, especially ones that are not created with VS to begin with. To get to the plain Jane adding of a web service you have to walk through some additional steps.A) Select the "Add Service Reference..." option, then, click on the "Advanced..." button.B) Click on the "Add Web Service" button from the advanced screen:Allright that should do it to bring you back into the old web service ways. Cheers,B --- ## CF: The varExists() function — Expanding IsDefined() to work with regular array and associative array notations. URL: https://www.boncode.net/cf-varexists-function-expanding Date: 2010-07-17 Many times while working in ColdFusion code I am encountering the simple need to check for the existence of an index in an array, e.g. myArray[3]. While other languages may have had easier checks on this, in Adobe ColdFusion, I unfortunately, have to work around this scenario with many lines of code or different functions to call. Thus, I am able to construct fully well formed variable references and use them, but cannot check their validity in a simple fashion.For example, I can't do a simple call to a universal function such as IsDefined("myVar[3]"). In this simple scenario we could have used ArrayIsDefined(), however, the scenarios I normally deal with are not so simple. In my scenarios I am not sure about whether "myVar" is an array in the first place or whether the index is numeric. E.g. I may need to check myVar[checkIndex]; this maybe a strucure with an associative array notation which takes me back to square one. Along these lines, multi-dimensional arrays such as myArray[3][4] are equally unqualified for ArrayIsDefined().Similarly associative array notations that can be used with structures, e.g. myStruct["testNode"], equally do poorly on these checks and could require some sort of special checking and more lines of code.How about a combination of things:TestStruct.Animals['species'][1]['counts'][2]All of these scenarios go beyond the ability of IsDefined() or other functions and cause more code to be written. Maybe this would be an opportunity to expand in future version of ColdFusion but for now we're stuck or are we? (yeah, rhetorical question this one).I made this a test project and developed an alternative function, varExists(), to IsDefined(); it may not be usable in all scenarios but will come in handy in coding.The sample implementation can be downloaded here (varExists.zip (3KB)).The first objective was just to be able to handle the complex notation scenarios that commonly fail under IsDefined().e.g.:varExists("TestStruct.Animals['species'][1]['counts'][2]") should operate without a hitch on complex variable notations. While at the same time maintaining full backward compatibility with IsDefined(). So you should be able to do things like this varExists(varName), varExists should check for the existince of the content referenced by the content of varName, e.g. a string such as "TestStruct.myArray[2][1]".But, why stop there, the next thing that I commonly do once I check for the existence of a variable is to retrieve its value for some sort of operation, so I added this option as second argument. Thus, varExists will automatically return the value referenced as part of its operation if "True" is passed as second argument, e.g. varExists("myUserArray[33]",true). This would return the UserName at array index position 33.Another common task I perform when the value is not known or "undefined" is to assume a default value. Thus, I added this as third parameter. When a third parameter is supplied it will be returned, when the actual variable reference is undefined.For example:varExists("myUserArray[33]",true,"John Doe")would return "John Doe" if the array index 33 is not populated for some reason.The example code has the test array and unit tests with sample scenarios. The hope is that eventually the ColdFusion language can accommodate these type of operations natively.Happy experimenting.Cheers,B.Addition:The Railo CFML engine does not exhibit the flaw outlined in this article. Thus, if you use Railo, you probably will not encounter scenarios in which you can construct a valid variable reference but cannot check for its existence. The IsDefined() function works as expected, however, if you want the expanded functionality of retrieving variable values etc. you would still need to use the varExists() User Defined Function (UDF) provided here. Best,B. --- ## CF: Connecting 64-bit Coldfusion to 32-bit MS Access databases URL: https://www.boncode.net/cf-connecting-64-bit-coldfusion-to-32 Date: 2010-06-01 First off, don't ask me why you would want to do this, just go with the flow.In other words, let's not get bogged down on how you should not put anything on Microsoft Access anyway and accept the fact that there is still many applications that are perfectly happy with it ;o)The problem has existed for a while but it dawned on me more clearly as I was sitting in on a hands-on beginner CF class at NC Dev Con and several of the participants immediately ran into this with their brand spanking new, high powered, Windows 7 64-bit computers.So it seems more common that you would want to take the 64-bit edition from Adobe for a spin. But as soon as you attempt to connect to anything 32 bit you receive non-descriptive errors such as:"Unable to update the NT registry. Variable DRIVERPATH is undefined."Maybe dropping those options from the list of available drivers would have been wiser and less frustrating for users. Something for Adobe to ponder about I guess.Microsoft does not have any (as of this writing at least) ODBC drivers for 64-bit Microsoft Access; in general, not much ODBC activity in a long time from the Microsoft camp. So, you might be well able to load up Office 2010 in 64 bit format; using the resulting databases for your projects, however, is a fairly complicated tasks.As with all workarounds there are many steps to complete, so here we go:1.) Download and Install 64 bit SQL Server 2005 Express Edition. You cannot use SQL Server 2008 Express edition, so don't try. It is lacking the needed OLE DB Provider.2.) Download and Install Management Tools3.) Download and Install Microsoft SQL Server JDBC driversFor steps 1 through 3 here is a nice tutorial by Steve Brownlee - Fusioncube4. ) Copy your MDB somewhere, e.g. c:\temp5.) Created Linked Databases using Microsoft Jet 4.0 OLE DB Providera) Linked Server Menu. Right click on the Linked server node and then click on "New Linked Server..." sub-menu option:b)linked server dialog. Product name can be anything you like. Data source should point to your access file:6.) Create DS in CF Admina) create type otherb) specify data source connection properties7.) Create sample code for CF. Your query code has to be changed, so you might want to create a variable to hold your prefix to your tables in case you change from 64 bit to 32 bit and vice versa.Note that you have to use the four part syntax to query out of a linked MS Access to SQL database. You are just omitting two parts, there is also another syntax possible : Openquery(Linked_Server, 'Query') which I will not dig into.To specify a query table in your access database you start with the name you have entered in SQL Server while the creating the link. In my case this is "Northwind". This name is followed by three periods (...) and, then, by the actual table name:e.g. : NORTHWIND...EMPLOYEESHere is my example code:HelloNW.cfm file:<cfquery name="selNorthwindEE" datasource="Northwind">SELECT *FROM NORTHWIND...EMPLOYEES</cfquery><cfdump var="#selNorthwindEE#">8.) EnjoyCheers,B. --- ## CF:Flex: FOF: Flex on Fusion, thoughts on what it takes to create a unified framework URL: https://www.boncode.net/cfflex-fof-flex-on-fusion-thoughts-on Date: 2010-05-17 The SituationIf you have worked on either Flex or ColdFusion you know that nowadays there is more development frameworks than people know what to do with.At one point having a consistent pre-defined path to application development on either of these platforms meant you had to invent wheels many times over. Now, the situation has changed to one where you attempting to decide which framework to use; long discussions and passions are aroused.At some level this has become as counter-productive as the use of no framework was before.Here are the commonalities I noticed:a) Frameworks are for developers:You have to learn the platform, learn the framework and have some sort of knack for writing code.b) Frameworks only cover one or the other technology.They do not span technologies, even if your application is expected to. Thus if you have to write an app that uses a ColdFusion back-end and a Flex front-end; you have to put the puzzle together yourself. One may even say we are back where we were several years in the no framework days.I understand, there are wizards to get you started in both directions, e.g. CF wizards for flex, and flex wizards for CF, but a wizard a framework does not make ;o)Don't get me wrong. There are some cool things being done with scaffolding to generate fully fleshed out UIs that are generated from a database, a la Ruby. For example, check out Apptacular.c) Frameworks focus on developer application partsFrameworks focus on allowing programmers a base structure that can expanded. Most of this centers around the use of the MVC pattern in one form or the other. However, less attention is given on other services needed in order make an application complete or usable.For example commonly left to the programmers are things like internationalization, user management, rights management, currency and data management, skinning management.The ThoughtUsing frameworks either on ColdFusion or Flex is nothing new. Creating a Framework that spans both is. Thus the idea of Flex on Fusion (FoF) came into my head and just would not let go. I thought, well, now what? Do you really want to create yet another framework even if the idea sounds cool. Who would want to learn it? and Why?But, for some reason, the idea was persistent and would not easily go away by itself.More thinking occurred and I do think that this framework has to enable the user (not necessarily a developer) to quickly built full applications. More like the Magic environment, more graphical, less focus on writing code.And so I am putting it out here to gather feedback and expand on it.The idea is not to obsolete all other frameworks, rather build a more user centric framework that can be used along with other frameworks. Thus, you should be able to use platform level frameworks to construct sub-pieces. Use the stength of each plattform, CF, for the database and logic, Flex, for advanced visualation and UI, in a combined stronger form.I am envisioning a startup process that walks the user through the basic steps, e.g. pointing at the database and determining a subdirectory to write the model implementation, etc. This is similar to other scaffolding models; however, the application that is built will also have a user and security model. More importantly, after the basic build is finished, there should be a UI that can be used to define the application further without coding. Adding more data/screens should all be doable via UI. In the extreme thought the UI would expose an IDE for the pieces that require coding.Once an application is generated, it can extended easily be extended while it is running by users with sufficient permissions.I will post some more detail describing screens and workflow in a bit.Cheers,B. --- ## Java: VisualVM “Add JMX Connection…” missing from file menu URL: https://www.boncode.net/java-visualvm-add-jmx-connection Date: 2010-04-15 A quick note as I had not seen this before.This occurred to me on windows 2008 R2 server platform.I looked and even compared log files among computers could not find anything conclusive that would cause this. But for some reason the option to add a JMX Connection was not available any longer in VisualVM tool.Not in context menu and not in File menu.Much trial and error followed but the solution was to redo the installation.Thus, the only thing that worked is to delete the VisualVM directory, re extract the zip files to a different directory, then start the VisualVM exe with Administrative privileges.After the initial calibration, the Menu item for JMX Connection was available again.Yohoo!-B --- ## CF: Java: Using free VisualVM tool to monitor running ColdFusion Servers URL: https://www.boncode.net/cf-java-using-free-visualvm-tool-to Date: 2010-04-15 You may have had a chance to use the VisualVM tools in the past and found them helpful to get an idea on what is actually happening on the VM while your code is running.The VisualVM tools can help you detect memory leaks in progress as well as other constraints on your server before it crashes. But even after a crash these tools are helpful. The tools are very graphical and easier to use than attempting to read thread dumps and heap dumps manually.Here are some simple steps to use this great tool set with ColdFusion.1) download java jdk 1.6.09 or laterhttp://java.sun.com/javase/downloads/index.jsp2) Download Visual VMhttps://visualvm.dev.java.net/3) Configure Coldfusion jmx accessBest way is to go to Coldfusion Administrator Java and JVM settings section.Add the following parameters:-Dcom.sun.management.jmxremote.port=8701-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=falseYou can decide whether to use ssl or not, and also on the port to use. If you want to use jmx authentication I would recommend you read:http://java.sun.com/javase/6/docs/technotes/guides/management/agent.html#gdenl4) Configure your Visual vm start up to point to your jdk if you have not set environmental variables:e.g. on Windowsif you extracted the visualvm files into C:\Java\visualvm_122andYour JDK is located in C:\Java\jdk1.6.0_19then you can use the following command line:C:\Java\visualvm_122\bin\visualvm.exe --jdkhome "C:\Java\jdk1.6.0_19"I put it in a batch file that I can start easily.5) Start up the VisualVM tool (it may have to go through calibration first, simply acknowledge), then, and establish a connection a JMX connection by right clicking on the local node and choosing "Add JMX Connection..."6) Add connection parametersNow you should be able monitor your server as it runs. I found this to be more stable than the Server Monitor in Enterprise versions of ColdFusion especially under load. It does not have all the same information but you can get a detailed breakdown of VM memory use.To get into the details of which CF code is using memory you have to generate a heap dump and use the heap walker to run the analysis. All the classes starting with cf... are your code running on the VM.You also have the option to monitor remote ColdFusion servers as well. You monitor multiple remote and local CF instances in one console, however, unlike the local monitoring, you cannot generate a heap dump when using remote connections.Creating a remote connection involves two steps in VisualVM after you enabled jmx access on ColdFusion.a) Adding a remote host. You do that by right clicking on the "Remote" node in VisualVMb) Specify the host name and display name and connection jstatd port (this is the same port you set in your CF JVM start up parameters). You will need to use the Advanced Settings dialog to do this. The port should be the same you set in the ColdFusion Java and JVM settings for that instance of CF.c) Set up a remote JMX connection by right clicking on the server name node and choosing "Add JMX Connection...". This will bring up a similar window as in step 6 above. Fill in the server and port information and you should be able to see your server.Another common use for the VisualVM tool is analyse a Heap Dump after a VM crashes due to memory problems. You can open and walk through the final VM Heap state. To make ColdFusion produce a heap dump you will have to change the jrun.config file and add this config option:-XX:+HeapDumpOnOutOfMemoryErrorIf there is a crash the heap dump should be a text file located in your {coldfusion}\bin folder.More information on how to use the VisualVM tool is available on the VisualVM website; definitely worth a look. Cheers,-B. --- ## CF: Dynamically changing Application.cfc using server specific configuration files URL: https://www.boncode.net/cf-dynamically-changing-applicationcfc Date: 2010-03-16 This started as I was reading an old post from Ben Nadel.I did see that Ben was using a methodology to set up Application startup parameters in a special config function and commented on it.I wrote about our experience with externalizing these parameters into specific configuration files instead and Ben stated that copying could be a problem if you override the config files.Here then is my thoughts on how to keep external xml files to describe application specific settings, e.g. production vs test vs datasource names, timeouts, etc.Nothing new here right? But the goal is to be able to keep the configuration files without a headache and conflicts.Lets take a sample set of parameters in a file like so:<wddxPacket version='1.0'><header/><data><struct><var name='REQUESTERRORHANDLER'><string>RequestErr.cfm</string></var><var name='VALIDATIONERRORHANDLER'><string>ValidationErr.cfm</string></var><var name='EnableErrorHandlers'><string>No</string></var><var name='DEBUG'><string>No</string></var><var name='ADMINEMAIL'><string>change_please@mycompany.com</string></var><var name='DATASOURCE'><string>APPDS</string></var><var name='APPLICATIONNAME'><string>StandardName</string></var></struct></data></wddxPacket>The trick here is to be able to have a system which allows you to keep different configuration files without fear of overwriting them; and, even if you do copy over them by accident (or even if you have many different ones), the system will be smart enough to pick the correct one.My implementation (Application.cfc) for this looks like this:<cfcomponent> <cfscript> //start off by reading config file, read contents into this.stcConfig initConfig(); //set application options from config file this.Name=this.stcConfig.ApplicationName; this.SessionManagement="Yes"; this.SessionTimeout=this.ConfigTimeout; //other application parameters can be set </cfscript> <cffunction name="onApplicationStart" output="No"> <!--- no need to lock app scope variables in this function unless called from another function ---> <!--- now make the config file data available to the application scope (bsoylu 03-17-2010) ---> <cfset Application.stcConfig = this.stcConfig> <cfset Application.ConfigFile = this.ConfigFile> <!--- we are setting some dynamic Error Handlers ---> <cfif IsDefined("this.stcConfig.EnableErrorHandlers") and this.stcconfig.EnableErrorHandlers> <cferror type="REQUEST" template="#this.stcConfig.REQUESTERRORHANDLER#" mailto="#this.stcConfig.AdminEMail#"> <cferror type="VALIDATION" template="#this.stcConfig.VALIDATIONERRORHANDLER#" mailto="#this.stcConfig.AdminEMail#"> </cfif> <!--- do other stuff now ...---> </cffunction> <cffunction name="OnRequestStart" > <cfargument name="CallPage" type="string" hint="This is the page the user is calling. This argument is populated by CF automatically."> <!--- do your request work ---> </cffunction> <cffunction name="OnRequestEnd"> <!--- finish up your request code goes here ---> </cffunction> <cffunction name="getIP" returntype="string" access="private" hint="return server main IP address"> <cfscript> //get Inet Address type object from JVM var objInetAddr = createObject("java", "java.net.InetAddress").getLocalHost(); return objInetAddr.getHostAddress(); </cfscript> </cffunction> <cffunction name="initConfig" access="private" output="Yes" hint="load config file"> <cftry> <!--- first check for server specific config file config.XXX.XXX.XXX.XXX.xml, e.g. config.196.18.12.78.xml ---> <cfset strConfigFile = getDirectoryFromPath(getCurrentTemplatePath()) & "config.#getIP()#.xml"> <cfif not FileExists(strConfigFile)> <!--- fall back to global config file ---> <cfset strConfigFile = getDirectoryFromPath(getCurrentTemplatePath()) & "config.xml"> </cfif> <cfif FileExists(strConfigFile)> <cffile action="READ" file="#strConfigFile#" variable="strConfigWDDX"> <cfif iswddx(strConfigWDDX)> <cfwddx action="WDDX2CFML" input="#Trim(strConfigWDDX)#" output="this.stcConfig"> <!--- save the config file that we use ---> <cfset this.ConfigFile = strConfigFile> <cfelse> <cfthrow type="INIT" detail="Incorrect Configuration File. No WDDX detected."> </cfif> <cfelse> <cfthrow type="INIT" detail="Missing Configuration File. No global or server [#getIP()#] specific configuration file found."> </cfif> <!--- prepare timeouts ---> <cfif IsDefined("this.stcConfig.SessionTimeOutMinutes") and Val(this.stcConfig.SessionTimeOutMinutes) GT 0> <cfset this.ConfigTimeout = CreateTimeSpan(0,0,Val(this.stcConfig.SessionTimeOutMinutes),0)> <cfelse> <cfset this.ConfigTimeout = CreateTimeSpan(0,0,20,0)> </cfif> <cfcatch type="Any"> <cfoutput>#cfcatch.detail#</cfoutput> <cfabort> </cfcatch> </cftry> </cffunction></cfcomponent>The idea here that the Application.cfc selectivly loads configuration files. It looks for a server specific configuration file, e.g. config.10.10.1.100.xml , then a global configuration file, e.g. config.xml.Allmost all of the important work occurs in the initConfig() function. It determines the machine's IP address then alternatly looks for a machine specific configuration file, followed by a global configuration file. If neither can be found, we throw an error.Thus, even if I copied my development server's configuration file by accident to the production server it would not be of consequence for the production server. I am of course subject to the normal human errors. If I delete all configuration files I am hosed anyway etc.Try it out and let me know if this helps.Cheers,-Bilal --- ## CF: Flex: PGP Implementation for ColdFusion URL: https://www.boncode.net/cf-flex-pgp-implementation-for Date: 2010-01-28 Pretty Good Privacy (PGP) is a computer program that provides cryptographic privacy and authentication. PGP is often used for signing, encrypting and decrypting e-mails to increase the security of e-mail communications. It was created by Philip Zimmermann in 1991. The use of PGP in file exchanges has increased over the years and has become a common way of securing file contents. Thus, encountering this in more and varied projects is not unusual. There are several implementations for popular platforms such as Java and .net; I classified them into brought camps of heavy commercial, or hard to use open source; thus the availability of easy to implement PGP solutions for ColdFusions is limited. In particular, I found existing implementation rather difficult to use. Thus, I embarked on this project. To make a long story short, I ended up using the underlying work of the league of bouncy castle folks. The complete source code for those libraries can be downloaded from there. I implemented the most common scenarios (generate keys or key rings, encrypt and decrypt) and exposed all this through a ColdFusion component to the world. Thus the effort to use of PGP is reduced to one liners of code (which I like). Along the same lines, if you use Flex and needed a library to encrypt/decrypt this implementation can easily used as backend for that kind of scenario. A few tweaks to the main component should allow you to call on all the functions, read, write, generate keys etc. Of course, there is so much more that can be done with PGP. Time permitting I may expand this implementation to expose other functionality. You can download this from Github (https://github.com/Bilal-S/cfpgp/releases/tag/2.0.0). Cheers, -Bilal --- ## CF: Connecting ColdFusion to Microsoft Azure SQL URL: https://www.boncode.net/cf-connecting-coldfusion-to-microsoft Date: 2010-01-07 I am impressed by what Microsoft has been able to create with the Azure platform. The more I play with it the more I like it. What impresses me most is how simple it is to get going (I am comparing with Amazon). The big caveat here is that you use MS technologies. If so, Azure should be on the short list for evaluation.However, and, here I go again reversing myself, if you want to connect a ColdFusion front end to a Microsoft Azure SQL back end, things are a little more quirky. Please don't ask why you would do such a thing, just stay with me in that it is highly cool ;o)First, you should evaluate whether your application will give to this kind of setup. On the ColdFusion side you should have good control on the amount of data you exchange with the database(pagination and other techniques); you also should have some tolerance for higher latency; there is delay in the round trip to get data from Microsoft etc. Of course the usual evaluation of whether you are ok with hosting data in the cloud should take place. But on the other hand, taking this for a spin is easy enough.In my setup I am hosting the CF server on my laptop and MS is supplying the database.1) Learn about Azure: Learn about Azure things and then Create Account2) Create your first database instance online using your browser3) Get your tools. You do not need to download the Visual Studio or other SDKs to work with SQL Azure, but you will need to use the SQL Server 2008 R2 Management tools. Currently only available as CTP edition.4) Optional: Migrate some data. For me, using the script wizard in the Management Studio worked the best. You can switch it to produce SQL Azure specific scripts, but you still have to tweak them. Your primary keys have to be clustered when creating tables.e.g.:CREATE TABLE [dbo].[TestTable]( [Test_ID] [int] NOT NULL, [TestName] [nvarchar](50) NOT NULL, [TimeZoneOffsetHours] [smallint] NULL, [TimeZoneOffsetMins] [smallint] NULL, CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED ( [Test_ID] ASC)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)5) Once you have some data we start with the ColdFusion parts. I have not been able to use the Adobe supplied drivers. I had to download the Microsoft JDBC 2.0 drivers. When you extract the jdbc drivers there are two .jar files. For CF you will need to use [sqljdbc4.jar]. Copy this driver into [cfroot]\lib folder.6) Restart ColdFusion7) Configuring your Data Source in the ColdFusion administrator. Here it gets a little complicated. You need to create a data source of type "other". Also, you cannot use the connect strings that are supplied by MS directly, though pieces are useful. The current stance is that Microsoft does not support JDBC connection but if you can work it they are fine with it. To make it simple I am attaching an image: (please note the way in which we have to set the User name)(replace myID with the database User ID and myServer with your server name from Azure):8) Configure your connection settings. The Azure platform will drop your connection frequently. So maintaining connection is not really an option. This is what worked best for me to make it appear as if we had no connection issues.Ok, hopefully this all worked out for you and you can take this for a spin.Cheers,Bilal --- ## CF: Parsing Complex Fixed (Flat) Files URL: https://www.boncode.net/cf-parsing-complex-fixed-flat-files Date: 2009-12-24 Despite many years of XML, the use of simple and complex flat files as a means of exchanging information between systems is still fairly common.Parsing simple, tabular, flat files like the one below does not really pose a large challenge as either the OS (Text Drivers) or CF (CFHTTP) have tools to read them in without much fanfare.Example 1: Tabular Fixed FileHowever, many times over, the examples are not as simple. The data on each row may be different; relationships may exist between lines of data etc.Example 2: Complex Fixed FileFor the complex files we normally write specialized parsers or transformations. Certainly a whole industry exists that deals with Extract Transform Load processes. Either choose requires considerable programming efforts. After writing a parser for the umpteens fixed file that someone wanted to have loaded, I thought there needs to be a better way. The short of all this is that I created a more generic component to deal with this in native ColdFusion. The solution was to split up the code and the file definition. Thus, in order to parse complex files, you provide an XML definition file which describes the flat file. Then call the component to do the heavy lifting.Example 3: Flat File Definition XMLThe outcome of such processing are standard ColdFusion objects that are easier to deal with and require less programmatic effort to implement.I posted this project on RIAForge (FixedFileReader). It contains examples for different scenarios of varying complexity. I added skeletons for EDI X.12 and VCF4 formats.May not work for all, but if it does, it is likely that it will save a lot of time.Cheers,Bilal --- ## CF: Controlling Time Based Runtime Exceptions URL: https://www.boncode.net/cf-controlling-time-based-runtime Date: 2009-11-18 Ultimately time controls everything. This is true in larger scheme of things but as well in writing and running ColdFusion code. Fortunately, many CF tags have built in time controls in forms of exceptions that can be thrown when a pre-specified time has been exceeded. Most tags implement this through a timeout attribute.You, then, use a CFTRY/CFCATCH combination to handle timeout occurrences, e.g. a web page failed to respond, or FTP didn't connect, etc.However, this system breaks down if your intent is control multiple tags in combination, e.g. a combination of CFHTTP and CFFTP may take up to 30 seconds though individually CFHTTP or CFFTP may consume a variable amount of time.Similarly, you are running a multitude of small steps in a loop, e.g. loading 1000 records, or displaying 500 lines. Though each line will only take a fraction of a second to process the number of lines in aggregate will blow you out of the water.Normally in these cases we would wait on an overall page time out if we had one, then produce a generic catch all message saying your page has timed out and good luck trying this again.This may suffice generically speaking, but may prove to be frustrating for users and visitors of your apps and sites.What if you could instead be more pro-active. What if you could predict how long your processing is going to take, even on shared servers with varying loads?What if you could give users options to either proceed, adjust your number of iterations, or simply stop early because you will never finish the task at hand in the time given.Ideally your code would be very compact:<!--- check prediction ---> <cfif objTC.WillTimeout()> <!--- we will timeout lets do something about it ---> ...Conceptually speaking this could have been done for a long time in CF, but practically I have seen few implementations.Let's look at what it would take to make this prediction using a scenario in which we have a repetitive core process that we need to time. Thus, it would be all about the ability to measure time for each loop. Thus we woulda) need to start a timer, e.g. GetTickCount()b) end the timer, e.g. another GetTickCount()c) measure the difference between start and end timed) use the remaining iterations to come up with how much more time we needSimple, right? Indeed it is. But the downfall is that it doesn't work.The system breaks down because of the high variability in practice between each iteration of the loop. Using the built in CF function GetTickCount() we could establish a start and end time. But, when we measure the execution time between the two tick counts the results in this realm change quite a bit.So, will we have to implement something complex using Java JETM instead to get this working? You probably could, but it isn't necessary if we add a dose of statistics to the whole puzzle. Here is a modified approach:a) establish statistical validity threshold in number of iterations (e.g. how many time do I need to have gone through the loop to have a valid sample)b) still need to start a timer, e.g. GetTickCount()c) end the timer, e.g. another GetTickCount()d) measure the difference between start and end timee) update your statisticsf) if validity threshold has been reached make predictionThis does seem to work a lot better but requires many more lines of code. Rather than put all of these lines of code into each template, I have abstracted the needed calls into a component.I would initialize the component (objTC) with the number of iterations (number of times I would need to go through the loop) and how many times I will need to have completed the loop to get a valid time prediction. In my example this would be 1000000 iterations with 150 completions. Or, something like this:<cfset objTC = CreateObject("component","TimeControl").init(1000000,150)>Then within the loop I would start and end the main timer like so:<!--- start measuring ---><cfset objTC.start()>End Measuring:<!--- end measuring ---><cfset objTC.end()>Now that the component takes care of all the nasty statistics stuff I can keep my main code simple and have some functions to use to either provide feedback to user, or just check on the status of things.E.g. I could provide feedback like so:<cfif objTC.HasValidAverage()> <!--- send the expected time to user when this process will complete ---> <cfoutput> Expected completion at #objTC.getFinishTime()# or (#objTC.getFinishSeconds()#seconds) <br/> </cfoutput> <cfflush>This is just a sample on how to handle it. I have put several more functions in the examlpe to play with. It may work well for some of your scenarios or not all. In any case, I do believe an improved feedback to user and more predictive code behavior based on execution time will reflect well on you as programmer. So feel free to play with samples and see whether this can get you started.The full sample code can be downloaded here.Cheers,-B --- ## CF: Meetup presentation about debugging materials (Nov 12, 2009) URL: https://www.boncode.net/cf-meetup-presentation-about-debugging Date: 2009-11-14 Thanks again to everyone attending the presentation. The goal was to get an idea about debug space and think about attacking debug problems by first identifying what area they originate from. Hope this gave everyone to use.Also we discussed with special focus on time based debugging from the performance perspective as well as from the perspective of handling time based exceptions predictevly. Dowload presentation and code now.Several questions regarding the use of CFDUMP came up and here are couple of links to deeper treatment of advanced CDFDUMP tag in CF9. Additinal attributes can be specified to tweak its behavior:CFDUMP in CF9Cheers-Bilal --- ## CF: CFinNC presentations URL: https://www.boncode.net/cf-cfinnc-presentations Date: 2009-10-21 Hallo everyone. First thanks for attending my sessions. If you did not attend and wanted to take a peak at what we covered please feel free to review the slides. Of course more fun was had during the sessions ;o)Download Beginning Debugging SessionDownload Advanced Debugging SessionI have inlcluded more slides and examples than we covered hoping that they can be usefull as well. All my material are distributed under creative commons license. Feel free to contact me with questions or comments.Generally, this conference showed that the spirit of CF is alive and well. It was an all volunteer event from the organization to the speakers and all the things in between. It introduced old and new people to CF and furthered networking in this Region. I hope we can make this an annual event.Cheers,-B. --- ## CF: CFinNC is all about debugging for me URL: https://www.boncode.net/cf-cfinnc-is-all-about-debugging-for-me Date: 2009-10-13 My presentations for CFinNC will be all about debugging. There is a lot to talk about crunched into two 50 minutes segments.Debugging is the often hated but yet nonetheless very important part of the developer's life fraught with lots of frustration and brief moments of glorious joy when the culprits are found. I am trying to give both the beginner and advanced audiences multiple techniques and tools to make the shining moments more frequent and frustrating times less so.Here is my official description about the overall presentations:Debugging can be a very frustrating exercise. Many times we find ourselves spending three times as long as it took us to develop the code to debug it. Especially code written by other developers seems time consuming to debug ;o)Understanding the debugging infrastructure will shortcut much of the confusion and help to quickly focus on the source of the problem. What can you do when has reached is limits? We will talk about techniques, tools, and tips available to the ColdFusion Developer to make this a "less" frustrating exercise.Hope to see you there,B. --- ## CF: CfinNC North Carolina ColdFusion / Flex / Air Conference – Oct 17-18, 2009 URL: https://www.boncode.net/cf-cfinnc-north-carolina-coldfusion Date: 2009-09-02 I will be presenting at the CFinNC conference this October. I will share some insight into working with SOLR, the search engine based on Apache Lucene as well as talk about debugging tips and tricks. If you have some insight you would like to share feel free to leave a comment.Here are the details on the conference:Registration for CFinNC is now open! CFinNC is a free web development conference held in Raleigh, North Carolina during the weekend of October 17th and 18th with an International line-up of speakers presenting on timely and relevant topics on web development. Thanks to the generosity of our sponsors and the creativity of the planning committee, registration for the event will be free and includes entry to the weekend event and to all presentations.In order to keep the event free we have removed some hard costs and some benefits you normally get from paid-registration events.Please be aware of the following:1) You are responsible for paying for lunch for both days. We have enlisted the services of a local caterer and will be providing lunch each day for $10/day. This includes a sandwich, chips and drink. Please bring cash the day of the event! We will not be able to process credit cards!2) Limited Edition, Collectible CFinNC conference t-shirts will be available for purchase for $15 with any proceeds going to offset costs and possibly sponsor a planning committee dinner (if we sell them all).Lunch and shirt purchase is completely optional. You may indicate if you would like to purchase lunch and/or a t-shirt on the registration form.For more information, please check the CFinNC website at: http://www.cfinnc.com-Cheers,Bilal --- ## CF: Adobe publishes hot fixes for ColdFusion URL: https://www.boncode.net/cf-adobe-publishes-hot-fixes-for Date: 2009-08-19 On August 17, 2009 Adobe published a number of security updates to numerous versions of ColdFusion. This has led to some scrambling to test these issues, get them patched etc.So far the hotfixes did not appear to break anything but the packaging is lacking as many manual steps will have to be completed.I could not quite understand why these hotfixes could not have been bundled together as one fix that can be applied.To make our lives easier I have built an installer for ColdFusion 8.0.1 running on Windows systems to do just that. You are free to use it at your own risk.The installer will update standalone installation of CF not J2EE/JEE installations.Thus the following hot fixes will be applied:CVE-2009-1872, CVE-2009-1875, CVE-2009-1876, CVE-2009-1877, CVE-2009-1878These JRUN only updates will not:CVE-2009-1873, CVE-2009-1874Cheers, --- ## Impressions from CFUnited, August 12 through 15, 2009 URL: https://www.boncode.net/impressions-from-cfunited-august-12 Date: 2009-08-19 Many people in the middle of a Golf course. Learned new stuff, rehashed old stuff. The greats of ColdFusion held court, and Flex was the up and comer with attitude.The good:Open source coldfusion is engaged and attempting to move things forward. Adobe is cooperating for now. Railo was there and willing; OpenBD was there in spirit.ColdFusion builder is here despite the CFEclipse and we can expect more opinions on why one is better than the other. Adobe did not want to play in this open source game.ColdFusion 9 will have some expanded licensing options to make it easier to host things in the cloud.ColdFusion has gained some momentum but still overall a nishe.The food was pretty good.The Bad:Presenters could focus more on content and less on opinion.Some are born to present; others not so.ColdFusion is still niche and we need to not get so high on ourselves.Flex purist insistance that they do not need to know anything about CF.No CFUnited backpacks for the masses. What is up with that?One hour barely covers anything technical well. More multi-hour tracks digging into topics would be helpfull for people seeking pure technology how to.There is probably more that I missed but there you have it.Cheers --- ## CF: ColdFusion Serialization via Java API URL: https://www.boncode.net/cf-coldfusion-serialization-via-java Date: 2009-07-29 This is a topic that has found many posts. Here is my spin ;o) Most of the posts focus on the success of serializing ColdFusion components. Though cool, many ask the same question: Why do this?Also to note is that ColdFusion has supported a mechanism to serialize complex data via WDDX for a long time (I believe since version 4).However, in my case, the need was not for serialization components but rather for compact serialization. In other words, use as little space (bytes/data) as possible. In addition, I needed to easily save and retrieve this information from a database in a text based format. Oh, yes, and handle complex data objects such as structures and arrays.WDDX, though usable, is very verbose and thus was out. Looking at the Java API and reading through posts I translated this, in the end, to two functions fSerialize and fDeserialize. You will need ColdFusion 8.0.1 or higher to make this work.The fSerialize function: <cffunction name="fSerialize" access="public" returntype="string" hint="uses java byte streams and Base64 encoding to serialize CF objects, this can be used instead of WDDX tag CFML2WDDX"> <cfargument name="input" type="any" required="Yes" hint="the CF object to be serialized"> <cfscript> var objByteStream = createObject("java", "java.io.ByteArrayOutputStream").init(); var objOutStream = createObject("java", "java.io.ObjectOutputStream").init(objByteStream); var objSerialized =""; //turn CF object in argument to out stream objOutStream.writeObject(Arguments.input); objOutStream.close(); //take outstream and make bytearray objSerialized = objByteStream.toByteArray(); //encoded it and return return BinaryEncode(objSerialized,"Base64"); </cfscript></cffunction>fDeserialize function: <cffunction name="fDeserialize" access="public" returntype="any" hint="uses Base64 encoded Java Byte Array and turns to CF object. This can be used instead of WDDX WDDX2CFML"> <cfargument name="Input" type="string" required="Yes" hint="the Base64 encoded ByteArray that used to be a CF object to be deserialized"> <cfscript> var objSerialized =BinaryDecode(Arguments.input,"Base64"); var inByteStream = createObject("java", "java.io.ByteArrayInputStream").init(objSerialized); var objInStream = createObject("java", "java.io.ObjectInputStream").init(inByteStream); var objCF = objInStream.readObject(); //return the read object return objCF; </cfscript></cffunction> These function on average were using 50% of the storage that a comparable serialized WDDX object would, so they achieved their objective for me. They will work on small components (cfc) but I have not tried to serialize very complex cfcs.Cheers,-Bilal --- ## VSTS 2008: Database Load and Unit Test using Load Agents URL: https://www.boncode.net/vsts-2008-database-load-and-unit-test Date: 2009-05-20 There had to be a secret to this. Reading through the documentation, looking at examples, load testing with VSTS 2008 seemed a sophisticated affair, alas, only if you are working along the most popular path. More specifically only for web application testing.I, being a renegade, wanted to use it to do Database Load testing. There are great new facilities in VSTS 2008 to create Database Unit tests but none speaks of how to do a load test.I thought it would be easy enough to adapt the techniques in web-testing to database load testing. I found out I was very naive. I should have caught on when:a) There was no documentation at all, no video, no web post, no nothing from MS or anyone having done this.b) The number of errors I was getting when even trying to run it with one agent.My test setup initially:a) One workstation running controller and VSTS 2008b) One server running VSTS Load Agentc) A beefy SQL Server 2008 box to be load testedLoad testing on my workstation was working great, everthing was as expected and I was hopefull that this could easily translate into working well on the agent system. In short, it did not:Here is the initial error I got:System.IO.FileNotFoundException: Could not load file or assemblyI thought the deployment was enabled automatically, playing with the deployment option on the Test Run Configuration was not very helpfull. I ended up copying the assembly files into the same directories on the Load Agent, only to get errors referencing core related assemblies of VSTS2008. So, I created install project to deploy those... you guessed it, a wild goose chase in which I tried so many different things only to end up banging my head against a concrete wall. I nearly concluded that VSTS 2008 could not be used to do load testing for a database with Load Agents when an idea struck. This one ended up working, but could have been easily documented. So Microsoft peeps take it to heart ...I changed the test rig in this fashion:a) Workstation with VSTS 2008 and controller + SP1b) Server with VSTS 2008 and Load Agent + SP1c) SQL Server 2008The solution, thus, is to install visual studio team system 2008 on the agent computer/server as well, then install the agent. What good is an agent that does not cover all test cases? That is something that Microsoft hopefully will resolve. There seem to be dependencies on VSTS core files, I played with it a little. You do not need:a) Any Crystal stuffb) SQL Server Expressc) C++d) dotfuscator stuffe) Documentation or redistributablesMy test where in C# so I installed on support for it and no other language.Cheers,Bilal --- ## Java: Connecting to MS SQL server with JDBC and JRE 1.6 URL: https://www.boncode.net/java-connecting-to-ms-sql-server-with Date: 2009-04-29 So,I have this little Java project which requires that I connect to SQL Server 2005. Something I have done many times. Download the JDBC drivers from MS and copy them into the lib directory and do your shindig in the connection to get going.But, this time things have changed and the installation instructions are worthless at best.Here is what I did:Downloaded the driver files from MS for JDBC 2.0Unzipped to directoryMoved jar files (there are two files sqljdbc.jar and sqljdbc4.jar) to my lib directorycoded my connector to use Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")Did some query codeAnd presto, nothing works as expected. Instead I get an exception with this in the stack trace:"The JDBC Driver version 2.0 does not support JRE 1.4. You must upgrade JRE 1.4 to JRE 5.0 or later when using the JDBC Driver version 2.0. In some cases, you might need to recompile your application because it might not be compatible with JDK 5.0 or later. For more information, see the documentation on Sun Microsystems Web site"Complete bogusness as neither Microsoft or Sun contain much info about how to solve this. So, head scratching starts followed by experimentation. Come to find out I made a mistake by copying both jar files packaged in the driver to lib. They contain similar classes and the sqljdbc.jar files classes' are used if both are copied. However, the sqljdbc.jar file classes are not ment to be used with jre/jvm 1.6+ . Why noone mention this in the provided install doc is a different question. Solution:a) Remove the not needed jar file (sqljdbc.jar) from lib directory orb) specifically declare to use only the right one (sqljdbc4.jar)Microsoft, please help us measly developers wasting time and state this in basic terms in your install doc.There you have it.Cheers, --- ## CF: Unable to perform cfflush in cffunction URL: https://www.boncode.net/cf-unable-to-perform-cfflush-in Date: 2009-03-28 OK. This is not an obvious one, so I decided to document this behavior.Say you have several functions in components processing away happily, and you want to give the user some feedback to keep him/her entertained as well as keep their paws of the back buttons etc..You think doing couple of flushes during your processing may be a good way until you try and get this error: Unable to perform cfflush. You have called cfflush in an invalid location, such as inside a cfquery or cfthread or between a CFML custom tag start and end tag. What to do? Since none of the hints apply to you. Your code looks like this:<cffunction name="fFlushIt" hint="flushes current content"><cfargument name="feedback" default=""><cfoutput>#Arguments.feedback#</cfoutput><cfflush></cffunction><cffunction name="fProcessing" returntype="numeric" hint="does processing" output="No"><cfset var x=10><cfset var y=20><cfset fFlushIt("Processing Complete")><cfreturn x + y></cffunction><BR><cfoutput>The result is: #fProcessing()#</cfoutput>here comes the digging into the code and making guesses part. It seems that there is one more scenario cfflush won't like and this is if you call in within a call-tree (yes even nested stuff) in a function that has the output attribute declared as "No". Maybe a hint like that could be placed in the error to avoid all that brain scratching and wondering that goes along with this?Anyways change the function like this and it worked. Yeah !<cffunction name="fProcessing" returntype="numeric" hint="does processing" output="Yes">Cheers, --- ## Oracle: PLS-00103: Encountered the symbol “” URL: https://www.boncode.net/oracle-pls-00103-encountered-symbol Date: 2009-03-26 Triggers, triggers and more triggers.Thousands of them. Ran the scripts into Oracle using ColdFusion instead of SQLPlus only to find out that I now had thousands of invalid triggers.A little puzzling, as the same scripts worked like a charm everywhere else. I go use the oracle web enterprise manager to see whehter I can recompile them and make a few valid. Nada!Everytime the Enterrpise manager tries to compile the trigger I get the error:PLS-00103: Encountered the symbol ""Here is a sample trigger with issues:CREATE OR REPLACE TRIGGER INS_MySuperTrigger BEFORE INSERT ON MySuperTriggerTable REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW DECLARE newid NUMBER;BEGIN If :new.MySuperTrigger_ID IS NULL THEN SELECT SEQMySuperTrigger.NextVal INTO newid FROM dual; :new.MySuperTrigger_ID := newid; End If;END;This is nuts. I use the generate SQL button of Enterprise manager to generate the SQL and copy and paste it into the Oracel SQL Developer UI, run the code without mods, and bingo; the trigger is valid and happy as a peach.What gives? Long hours wasted with different websites and options, casing, single and double quotes, Egyptian prayer beads..., you name it, I tried it.Until pulling a protocol sniffer to see what the difference is between Oracle Enterprise Manager and Oracle SQL Developer on the wire.Come to find out Oracle does not recognize Windows CRLF (Chr(13) + Chr(10)) as blank space, if you replace all the CRLF with LF this works like a charm. Seemingly, web based Oracle Enterprise Manager does not do this translation, while the Oracle SQL Developer tool does. Yack! Lesson learned, I now run the scripts through a parser before running them to Oracle via JDBC and get valid triggers all the time.Cheers, --- ## MySQL: frustration with login at the command prompt or the space character mystery URL: https://www.boncode.net/mysql-frustration-with-login-at-command Date: 2009-03-24 Many years ago when trying to use MySQL I ran into this, but only get to note it down now because someone else run into this problem. I searched and lo and behold not much info out there, so I thought maybe a couple of pointers would be worth while.When using the command line mysql tool you can specify the username and password of the user during login.Many manuals describe the syntax as:mysql -h hostname -u root -p passwordormysql --user=user_name --password=your_password db_nameYou think wow this is easy, right. I can interpret this very simply.I go to the command prompt and type:C:\>mysql --user=root --pasword=mypassbut to my astonishment I would get:mysql: unknown variable 'pasword=mypass'Here are couple of other beauties that are in the manuals and don't work at all like expected:C:\>mysql -u root -p mypassEnter password: ******ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)This could be very frustrating to someone new to MySQL on windows. Can't even login to get the client program started.The approach I found working for windows based installation is to ignore the manual and avoid space between parameters.Thus rather than using -u root, you will need to use -uroot. This will magically work. E.g.:C:\>mysql -uroot -pmypassWelcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 19Server version: 5.0.67-community-nt MySQL Community Edition (GPL)Type 'help;' or '\h' for help. Type '\c' to clear the buffer.mysql>Hope this will avoid some frustration out there.Cheers, --- ## CF: ColdFusion functions and the case of the mysterious space URL: https://www.boncode.net/cf-coldfusion-functions-and-case-of Date: 2009-03-19 Spent lots of time trying to find out why a space was returned from a function call to a function in a component. We would place the output directly into a html form text control, but a space would always be added to the front of the expected return string.Broke out the old Hex editor to save and check file contents. Output each character at a time, just could not see why this would happen.Many hours later, a headache started to kick in. Time for a break. Then, a hunch started knocking at the back of my scull and got louder and louder.To prove it to myself, I created an intermediate variable into which I stored the function result. When this scheme was used, no space. If I used the function output in place, space! It turned out to be the Output attribute of the function definition. You will need to set it to 'No'. If you leave it off and attempt to use the function in place, Coldfusion will introduce a space in the return. Very, very annoying.Here is sample code to reproduce the problem, two function that are identical except one has the output attribute specified; if you use the function 2 inline CF will produce a space in front of the output; see the output for f2 below:<cffunction name="fFunction1" output="No"><cfset var strReturn ="Hello World"><cfreturn strReturn></cffunction><cffunction name="fFunction2" ><cfset var strReturn ="Hello World"><cfreturn strReturn></cffunction><cfset sOutput1=fFunction1()><cfset sOutput2=fFunction2()><cfoutput>f1:--#fFunction1()#--<BR>o1:--#sOutput1#--<BR>f2:--#fFunction2()#--<BR>o2:--#sOutput2#--<BR></cfoutput>Output:f1:--Hello World--o1:--Hello World--f2:-- Hello World--o2:--Hello World-- --- ## CF: ColdFusion Impact of Content Type Declaration on the HTTP header with application/octet-stream URL: https://www.boncode.net/cf-coldfusion-impact-of-content-type Date: 2009-03-09 So, I encountered this little problem with XML transmissions for a customer. They would receive regular XML streams to update their data and all was working dandy, until one it didn't ;o)To CF it looked like all of a sudden the content of the HTTP traffic vanished, in other words we did not seem to have anything in GetHttpRequestData().content except for empty string.Of course, no one fessed up to having changed anything at all, so here I go digging through code and cannot find anything obvious and, then, I turn out the big guns: Protocol Sniffers and packet capture.Hah, I think, now I can show them that they are not sending any content, but instead I can see the content clearly in the packet capture which starts heavy head scratching and coffee sipping.More looking into code and I find that the only time we bypass GetHttpRequestData().content is if we are running a binary check, e.g. we have this condition: IsBinary(GetHttpRequestData().content)From the protocol packets I can clearly see that the content is not binary so, at first, I cannot imagine how this condition would be even trigger and bypass the remainder of the processing until, seing the light, I remove the condition.Bingo, now I can see content but it is all wrong. It looks like CF has processed the content of the transmission to numeric values instead of XML strings.Dang!So in the end, more digging to see that the http content type declaration of the originating transmission had changed from text/xml to application/octet-stream; it looks like whenever CF received this it automatically converted the perfectly fine XML into an octet stream, which, then, turned the content to be binary data instead of leaving it as simple string. A simple misdeclaration by the customer which caused this hoopla.So after much searching I wish I could have been able to tell the RAW data in the transmission from the interpreted data. This would have made the diagnosis much simpler. So Adobe, in the future please consider adding the raw information to the GetHttpRequestData function, so we don’t have to guess what parts are being interpreted and what the transmission contained.For now, I went back to the customer and asked them to correct their content declaration. --- ## CF: Coldfusion and the perennial rounding bug URL: https://www.boncode.net/cf-coldfusion-and-perennial-rounding Date: 2009-02-22 Through the years using any function that did implicit rounding in CF was not the safest thing to do. Many times when I thought this was resolved it came back with a vengeance to bite me in the you-know-what.Thus, the safe route to use is to go through the database to round anything, unless you really do not have any choice.This time it was the LSCurrencyFormat function which caused the headaches. It will round down at the .5 fraction rather than round up which is very annoying and disturbing at the same time. Here is a function specifically made for currency handling and it does not handle the basic calculations correctly.Example code (comparing the round behavior against LSCurrency):<cfloop from="0.001" to="0.009" step="0.001" index="fraction"> <cfset Amount = 1.10 + fraction> <cfoutput> number: #Amount# ls: #LSCurrencyFormat(Amount,'none')# compare to rounded #Round(Amount *100)/100# <BR> </cfoutput></cfloop>Unfortunately, I had flip back all the use of LSCurrencyFormat and pre-round the numbers via the database before passing them to this function. I do hope that Adobe does a little more testing on rounding for these in the future. --- ## CF: How to detect nested transactions within cftransaction URL: https://www.boncode.net/cf-detecting-nested-transactions Date: 2009-02-12 Sometimes it cannot be helped. You are expanding ColdFusion code and have to implement transactions. You have to, then, use components that cannot be changed, that, in turn, may have to do transactions. Now the problem, ColdFusion does not like nested transactions. Nested transactions are simply not supported.Well, at least if I could detect whether I am in a transaction I could write around this I think. But there is no way that I have found. No clear posting on how to do this.First approach I used was to create a function that would open and close a transaction, then detect the error thrown. If the error was thrown I was assuming that we were in a transaction and thus could not open a new one, a fuction like this:<CFSET var blnReturn = false><CFTRY> <CFTRANSACTION> <!--- emptry transaction tag ---> </CFTRANSACTION> <CFCATCH type="Any"> <CFSET blnReturn=true> </CFCATCH></CFTRY><CFRETURN blnReturn>Unfortunatly, this does not work. When CF throws an error for nesting, even within the try/catch block for the purposfully nested transaction, the transaction wrapper is removed. Thus you are hosed if an error occurs later down the execution.What to do then?After much researching and failure, here is the approach I did find working. The trouble with this is, that there is no guarantee that it will work in future versions of CF, which I hope will introduce a simple function like InTransaction() . We are using the ColdFusion Java implementation of the Transaction Tag to find out whether we have a current transaction. This is the fully wrapped function.<CFFUNCTION name="InTransaction" access="public" displayname="checks to see whether we are currently running a database transaction. returns true or false." output="No" RETURNTYPE="boolean"><CFSET var objTrans =""><CFSET var blnActiveTransaction=false><CFSET var objCurrentTrans=""><!--- Call to CF implementation of TransactionTag to expose Java functions ---><cfobject type="Java" class="coldfusion.tagext.sql.TransactionTag" name="objTrans" action="create"><!--- objCurrentTrans will become undefined if the Java function call getCurrent() returns Null,otherwise this returns a pointer to current transaction instance ---><cfset objCurrentTrans = objTrans.getCurrent()><cfif IsDefined("objCurrentTrans")><CFSET blnActiveTransaction=true></cfif><!--- return result ---><CFRETURN blnActiveTransaction></CFFUNCTION>This works in ColdFusion 8 and 7.Cheers. --- ## CF: Silent Server Side Debugging URL: https://www.boncode.net/cf-silent-server-side-debugging Date: 2008-09-13 So you get this call. Customer says "Nothing is working"; you cannot replicate. When you go to your application or site everything is working just fine.Have you been there? I have many a time. Wouldn't it be great to have had the debug output (classic coldfusion format) when the customer ran this?Well you can. You can change the way coldfusion does the debugging in a fairly straight forward fashion, i.e. you can capture all debug information and save it to files for later analysis by changing the debug handler.You do this like so:1.) Download the sample file (ToFile.zip).2.) Extract and place the file (ToFile.cfm) in your debug handlers directory [cfusion root]\wwwroot\WEB-INF\debug. If you installed ColdFusion in C:\CfusionMX8 this would be the final directory to place the file in: C:\CfusionMX8\wwwroot\WEB-INF\debug3.) Log in to ColdFusion Administrator and navigate to Debugging & Logging:Debug Output Settings4.) Change the " Select Debugging Output Format" drop down to "ToFile.cfm"For each page that you are generating a debug file, the time needed as well as the file name to which the debug information was saved will be displayed at the bottom of the screen.You have the option to specify a variable in URL, Form, or Variables scope.Specify a variable named: "DebugSilent" to suppress the bottom text altogether.Be careful though how long you keep this on as it will generate many files that need to cleared out.-Bilal --- ## Using Richt Text TextArea results in error (java.lang.Double cannot be cast to java.lang.String) URL: https://www.boncode.net/using-richt-text-textarea-results-in Date: 2008-07-29 Well you guessed correctly from the title. There is something odd going on.If we are passing on variables that are typed as numeric to an argument (height and width) that would conceivable accept numeric values we will get this error:java.lang.Double cannot be cast to java.lang.StringHere is sample code to reproduce this:<cfset iHeight=Val(200)><cfset iWidth=Val(500)><cfform name="myForm" method="POST" action="Self.cfm"><cftextarea richtext="true" toolbar="Basic" name="MyRTField" height="#iHeight#" width="#iWidth#" value=""> </cftextarea></cfform>This could easily occur when passing values as returns from functions. I found two ways of avoiding this.a) specifically declare variables as strings<cfset iHeight="200"><cfset iWidth="500">b) introduce space when passing arguments so as to force an implicit conversion...height=" #iHeight# "width=" #iWidth# " --- ## Micromarketing – Web 2.0+ and the evolution of human to machine marketing URL: https://www.boncode.net/micromarketing-web-20-and-evolution-of Date: 2008-07-01 It all started with search engines. People built sites and wanted other people to find them. This was a submission game. If I submit my site to X engines, it would increase traffic by n. This type of site registration work was done mostly by generalists maybe using special submission software to make this repetitive task easier.However, as search engines became smarter, this stopped working well. Besides, the few surviving search engines where exploring the mechanisms on how to make more revenue and would for that reason alone want to control the results more actively.Thus, a change happened in marketing. Even before this happened I did make a bold prediction that we would have this new aspect of marketing appear. The human to machine specialist. Marketing before this was mostly an affair of humans trying to convince other humans to do things or spend money on things and services they presumably did not think to be needing otherwise.The common incarnation of the human to machine marketer was the search engine specialist. Now, here was a marketer blissfully unconcerned about any human audience, rather focusing his energies on how to influence a system (search engine), which in turn would yield the outcome (higher search results). Whole companies specialized in this and are still today providing these services to others.Banner companies appeared, and a sophisticated system of banner advertising that was content sensitive appeared. Things evolved and no one in their right mind wanted to click on banners any longer. Google ads was begotten and as most things Google, it drowned everything else out. Google rules the masses with Add text banners.Now, we have this Web 2.0 happening and some of the paradigms with sites and submissions went out the door. So, then, you may ask, what with this web 2.0 stuff happening, whatever that is, will happen to the human to machine people? Will this have any impact on how marketing will evolve? Of course, thanks for the lead in .... If I were free to opine (which I am) I am going to make a prediction. Marketing will change once more to adopt to the next level of message delivery. Machine to machine marketing, or more specifically machine to machine Micromarketing, will emerge.Sure, obvious you say; maybe so, but let me explain my particular take on this. Imagine a web application in new web 2.0 style, highly interactive, highly social (high stickiness). Maybe you and your buddies are watching a bike race unfold online. As you are looking at the leader riding his Schwinn bike to victory, in the background systems (machines) are negotiating advertising rates with Schwinn based on this event, i.e. sports (special section bike related), audience (your buddies, target group size, average incomes and ages, etc.); Schwinn's systems may have to bid automatically against a competitor (automated market rate auctions) to gain the rights to transparently overlay a marketing message on the race as the race unfolds. This happens several times, as leaders change position, new Marketing messages are negotiated. This is target advertising driven to a next level, highly personalized, informative, automatic, integrated. Wow! You are right, there is no escape now, we will be truly slaves to our passions and exploited for our whims ;o)However, we are not there yet. There is a lot of work needed to create this next level of reality for marketing. Infrastructure and systems and protocols are just a few things.Negotiation protocol for marketing events. Probably something on top of WS standards, containing event information, exposure times, audiences, bid information.Advertising systems that can recognize types of events and are policy driven (executing against a pre-defined marketing strategy) to react to 1000s+ add requests per second.Micro-payment system: The ability needs to exist to pay for impressions or executions (clicks, seconds of videos watched, games played, names captured); maybe a quarter cent per incidence.Of course, some of this could be outsourced to specialist, which will then program your policies in their systems on your behalf. Maybe this could be the next Doubleclick service. Just say I didn't tell you so. --- ## Why the iPod must die URL: https://www.boncode.net/why-ipod-must-die Date: 2008-06-08 First of, I admit that I have owned an iPod. I owned it very briefly and did admire the attention that Apple has given to designing a well rounded MP3 player. However, I gave it away very quickly. I owned several other MP3 players before and after the iPod. The MP3 player that I am currently using is made by Samsung; and the main reason I bought it for was the radio tuner, followed by size and ease of use. Which overall brings me to the topic at hand, the future of the MP3 players in general and iPod in particular.The reasons that I did not keep my original iPod and also gave away multiple iPods that I received as promotional gifts and purchase bonus are very simple on one side but point out some of the issues that will, of course only in my humble opinion, doom its existence.To start with iTunes rubs me the wrong way. As a more technical person than the usual user, I did not like how iTunes took over my computer (with little to no choice), was consuming resources precariously and would not allow me to transfer tunes to anything else but iPod.I went on to discover something else about myself while dealing with the iPod (and other MP3) players. You could call it a journey of self discovery of sorts. Though the idea of downloading and assembling your own tunes seems pretty cool at first, the stark truth is, it is a LOT OF WORK.I did a completely statistically irrelevant survey to confirm my suspicions, I asked 7 people about their approach to iPod music management; astonishingly enough they did the same thing. Once they had loaded their favorite tunes, they made very few changes to their music play lists or downloaded music, ripped their CDs etc. Of course there are plenty of people who enjoy doing these things, they just don't seem to be in the majority.This must probably go under the more "dah" moments in live. We all relish the choice, but are not willing to put in the effort. Thus, I like the other people in my survey realized that this downloading and song organizing part of the iPod does not work for us as the maker intended.Thus, I am looking for the next wave of devices that truly promises to me the notion of complete choice by giving up any choice whatsoever. Counterintuitive you may say,"hah!" but not truly so I retort. I am thinking here of interactive, internet based radio available 24/7 with or without commercials, where I can pick a genre/type of music I feel like listening to, then I am able to make my preference known within the type by either fast forwarding or ranking the tunes. The new interactive radio station would learn my strange music ways and be able to quickly become adapt at knowing what to play to me, even be able to play medleys, cross music boundaries and present new bands/songs/artists to me.No more iTunes, no more needing to download anything, if I like a song I can ask for more frequent replay. I pay or not pay (via commercials) professionals to go out there and find the stuff I like. A serving of Indy... here you go, newest Pop/Rock, right away Sir...Now is this the stuff of far away future? Was I too quick to write the obituary of such an ingenuous device? I, of course, do not think so. The companies at the best position to deliver this are the companies that already sell us our daily other gadgets, such as the wireless carriers. They have realized this potential and working on services and devices that are nudging us ever closer towards this music nirvana. Unfortunately, they have only one way track thinking, e.g. make money directly on subscription services. Leaving out tremendous potential for ad dollars, cross marketing of goods (how about being able to buy tickets for a band you just heard that will be performing in your area. The carrier would know where you are located, they would know you just rated the song highly, bingo! you are ripe for the plucking.). I don't want to mention merchandising, but I think I just have. In other words there is potential beyond subscription for revenue.I also see potential for our friends from satellite Radio; they have the content, but they need to get off the bandwagon that radio is one directional. The radio of the future is interactive. Their gadgets need to be improved and maybe a free service would be available for people that do not want to do subscription, but would be willing to get commercials or merchandising messages etc. Wow, this could be cool.Apple is no dummy either. I believe, they have foreseen the death of the iPod already ;o) and I am convinced they are working diligently on the next best thing. What could this be? How could they capitalize on the trends I am predicting (crystal ball and all). iPhone is a start of course, but they just now get to a device that has sufficient bandwidth to access high quality music streams. What's the other way? Keep the best part of the iPod alive indefinetly and ensure it can get licensed easily and it gets into as many places as possible (Unfortunately licensing is not one of Apple's strengths). What am I talking about? The iPod's connection interface of course. Your radio clock has it, your car has it, your zip pocket in your pants will have it before you know it. It should become more ubiquitous than plain m&m's that don't melt in your hand. Thus, there could be a way in which the iPod could live on forever, however, its days as the music player of choice are numbered. --- ## FlexManiacs 2008 URL: https://www.boncode.net/flexmaniacs-2008 Date: 2008-05-25 Just returned from the Flexmaniacs 2008 show put on by Figleaf. I would classify this as mixed bag show. It is an impressive array of presentations, presenters and topics that were being covered. To me though this all seemed still a little rough around the edges; it is the second year so a little slack can be given.Half the presentations I attended ended up having a low value for me whether it was content, presenters struggling with presentations or topics, etc. Overall it was still a valuable conference to attend but the main part requiring improvement is to separate the bad presenters from the good and get to more consistent polished presentations. I have never seen a conference where half the audience would leave within 10 min of a start of a presentation; I can imagine this to be a good blow to many a soul attempting to present.In brief:the good: The conference is pretty long enough and provides good coverage of topics to sniff into into get an idea. The weather was nice ;o)the bad: Need better individual presentations and presenters. Would like to see options to rate individual presenters (online or after each show) . Topics should be better described ahead of time (I sat through an hour of a Flash presentation when topic was Flex). An individualized schedule should be printable from the website. More networking forums needed.Would attend again but pick only the day I think has the biggest bang.Cheers. --- ## CF: cfhttp and The column name “” is invalid. URL: https://www.boncode.net/cf-cfhttp-and-column-name-is-invalid Date: 2008-05-23 The other day we were looking at cfhttp to parse out a CSV (comma seperated values) file. It worked beautifully on the test systems but would not run when transferred to staging site.We would get this error consistently. The column name "" is invalid.None of the internet resources regarding this was very helpful. So after many trial and errors we discovered that the webserver we posted this to had basic user authentication switched on, thus we needed to provide username and password attributes of the cfhttp tag for this to work.Another perfectly good example of how the simple things get you. Would have been helpful too if the cfhttp tag could throw a more meaningful error. ---