Rip's Domain

CFWheels and implementing a Service Layer

Posted in Uncategorized by rip747 on June 2, 2012

A couple of weeks ago Doug Boude (rhymes with loud) authored a post about providing a service layer in CFWheels. I’m not going to go into what a service layer is or the use of it. If you want to know that, check out his post here.

Personally I never saw I use for this before. In keeping with the MVC tradition of doing thing, I always felt that these `services` could live in the model layer. However I absolutely love when people make me fall on my sword and I can clearly say that a service layer is definitely something that is needed in CFWheels. I still wouldn’t go so far as using it with a DI like WireBox, but who knows if I’ll change my mind about that later in life as well.

Following Doug’s post, I was able to implement a service layer with ease. The issue I had with his approach though was that it made testing very awkward. Having the initialization of the service layer living in the controller init method, made it a little hard to test, not impossible mind you, but a little harder then it should have been.

After giving it some thought, I figured out a way to not only make it so that the services initialized when CFWheels booted, but also was able to make the service() method global so that you can easily test against it.

If you take a look at this gist I created you’ll see the changes I made. Basically all I did was move his initServices() method into the events/onapplicationstart.cfm file and move the service() method into the events/functions.cfm file. The big change I made though was to the initServices() method so that it would automatically initialize any new services that you add to the services directory.

By putting these methods into their new homes, the services are loading once when CFWheels boots as apposed to every time a controller is created and also you’re able to access the service() method from anywhere in your application which make it easy to call in tests.

Advertisements
Tagged with:

rvm install 1.9.3 fails: truncated tar archive

Posted in Uncategorized by rip747 on June 2, 2012

installing ruby 1.9.3 via rvm and it fails with `trucated tar archive` which you can see by going doing `more ~/.rvm/log/ruby-1.9.3-p194/extract.log`.

the simpliest way to fix this is to uninstall rvm and reinstall. you can uninstall rvm by doing `rvm implode` and install by following the installation instructions: https://rvm.io/rvm/install/

xcode 3.2.6 installation failed: CSSMERR_TP_CERT_EXPIRED

Posted in Uncategorized by rip747 on June 2, 2012

when installing xcode 3.2.6 on OS X 10.6.6 (Hazard) the installation might fail with the following error when viewing the /var/log/install.log CSSMERR_TP_CERT_EXPIRED. this is because obviously the certificate has expired and xcode can’t verify that the certificate is valid.

a quick and easy solution is to change your system data to 1/1/2012 and then perform the install.

http://stackoverflow.com/questions/9953835/xcode-3-2-3-installation-failed-on-mac-10-6-3

Pitfalls with jQuery Mobile and how to over come them

Posted in Jquery, jquery mobile by rip747 on April 19, 2012

At work I’ve been tasked with creating a mobile app using jQuery Mobile and Phonegap. Needless to say, I’ve had nothing but issues. Below are some of the pitfalls that I’ve been running into and how to over come them. This post is a work in progress and I will add to it as things come up.

1) When creating additional pages, ONLY include the `data-role=”page”`.

First, let me explain what I mean by data-role=”page”. When you create your index.html for your jQuery Mobile project, you set it up like so:

<!– index.html –>
<!DOCTYPE html>
<html>
<head>
<title>My Project</title>
<meta name=”viewport” content=”width=device-width, initial-scale=1″/>
<link rel=”stylesheet” href=”css/jquery.mobile-1.1.0.min.css” />
<script type=”text/javascript” charset=”utf-8″ src=”js/jquery-1.7.1.min.js”></script>
<script type=”text/javascript” charset=”utf-8″ src=”js/jquery.mobile-1.1.0.min.js”></script>
<script type=”text/javascript” charset=”utf-8″ src=”js/phonegap-1.4.1.js”></script>
</head>
<body>

<div data-role=”page” id=”home”>

<div data-role=”header”>
<h1>Your header</h1>
</div>

<div data-role=”content”>
<p>The content goes here</p>
</div>

<div data-role=”footer”>
<p>The footer goes here</p>
</div>

</div>
</body>
</html>

Notice that we have our opening html tag, our head section with all our stylesheets and javascript includes, our opening body tag, our page div (containing the head, content and footer of the page), our closing body tag and closing html tag. This is standard when creating a html page and something we’re all use to.

Now let’s say you want to create another page called search.html. You would think that you would need to copy the head  section, body and html tags to the search.html page, but THIS IS WRONG! All the search.html page would contain is the page div like so:

<!– search.html –>

<div data-role=”page” id=”search”>

<div data-role=”header”>
<h1>Search</h1>
</div>

<div data-role=”content”>
<p>The form used to search</p>
</div>

<div data-role=”footer”>
<p>The footer goes here</p>
</div>

</div>

The reason for this is that jQuery Mobile will inject the search.html page’s content into the index.html via ajax. Because of this, if you put the html, head, and body tags into your search.html page, they will get duplicated. This can cause all sorts of issues that I won’t even go into. Just remember that you only need the html, head and body tags on the index.html page.

2) Disable ajax caching globally

Supposedly in jQuery Mobile disabled ajax caching of pages in 1.1.0. However, I was still having issue with the pages being cached so this was making development a real pain. Luckily you can disable ajax caching altogether by doing:

<script>
$.ajaxSetup ({
// Disable caching of AJAX responses
cache: false
});
</script>

Just put that in your head section on your index.html page and you should be golden.

3) Multiple events firing

This was a HUGE pain in the ass. You normally see this problem when submitting a form from one page to another. On the calling page, you might have some javascript that is bound to an event (like pageshow) that generates some dynamic content after doing an ajax call. If you look in your Net tab in firebug, you’ll notice that the ajax call will increment with each visit. So on the first visit it fires once, the second visit it fires twice and so on. The reason for this is because, again, of the way jQuery Mobile pulls in pages via ajax. Because it will pull the page in for each visit, it will continually add the code you want to run to the event stack on each visit.

Now I’ve seen people try to solve this by placing the code in the `pageinit` event since that only fires the first time the page in pulled via ajax, but this doesn’t work when you’re having to create dynamic content based on a search string.

The solution is quite simple once you think about it, just put your code on the index.html and delegate using the on() method. so for instance, if you have page with an id of `search` and you want to run an ajax request to get the results, you would do:

$(document).on(‘pageshow’, ‘#search’, function(){
// add code to get the search results via ajax here
});

Personally I would recommend that you put all the javascript code for your app in a js file and include that on your index.html page.

4) When inserting dynamic content into the DOM you must call trigger(‘create’) in order for the framework to apply the styling.

For my app, I have a function that automatically add pagination buttons (previous and next) to the footer. In my template the footer is just defined plainly:

<div data-role=”footer”></div>

In my javascript code, I add the pagination by calling the html() method on the footer object (code is summarized):

var loc = {};
loc.self = $(this);
loc.footer = $(‘[data-role=”footer”]’, loc.self);
loc.footer.html(pagination(loc.params.page, loc.results.PAGES));

The issue was that none of the styling was taking affect on the footer and the prev and next button were showing up as just links. I found in the jQuery Mobile form that you should call page() on the object after altering it, but this really didn’t work. After some more search I found that what I really need to do was call trigger(‘create’) on the object instead. the nice thing is that you can chain this after the html() call and it still works:

loc.footer.html(pagination(loc.params.page, loc.results.PAGES)).trigger(‘create’);

5) When creating a dynamic listview and inserting content into it, you need to call listview() and then listview(‘refresh’) to reapply the styling.

This is basically the same problem as #4 only this time we’re dynamically creating a listview an inserting content into it. In my app, I use Liquid as a templating language as it’s just making life soooo much easier then concatenating javascript strings. So to create my list view, I have it defined in my Liquid template like so:

<script type=”text/liquid” id=”arrestSearchResults-markup”>
{% if RESULTS.size %}
<ul id=”arrestSearchResults-listview” data-role=”listview”>
{% for item in RESULTS %}
<li>
<a href='{{LINK}}&jms_number={{item.JMS_NUMBER}}’ class=’arrestSearch-details’>
<img src='{{item.PHOTO_THUMB}}’ />
<h3>{{item.LAST_NAME}}, {{item.FIRST_NAME}} {{item.MIDDLE_NAME}}</h3>
<p>{{item.JAIL}}</p>
</a>
</li>
{% endfor %}
</ul>
{% else %}
<h3>No records found</h3>
{% endif %}
</script>

The target content div is defined plainly, just like my footer is in #4:

<div data-role=”content”></div>

to compile the template and insert it into the content div, I do the following in my code (code is summarized):

var loc = {};
loc.self = $(this);
loc.markup = $(“#arrestSearchResults-markup”).html();
loc.target = $(‘[data-role=”content”]’, loc.self);

// render the markup to the listview
loc.target.html(Liquid.Template.parse(loc.markup).render(assigns));
// refresh the listview
loc.target.find(‘ul’).listview();
loc.target.find(‘ul’).listview(‘refresh’);

Basically what I’m doing is getting the template markup and the content div and putting them into a variables. I then compile the Liquid template and pass in the assigns object that contains the information to render the template.

The key to all of this is the next two lines which finds the unsorted list (‘ul’) which contains the listview a just injected into the content div and calls listview() on it, this tell jQuery Mobile to treat the ul as a listview object. I then call listview(‘refresh’) to have the framework apply the styling to it.

6) When performing validation on a form, the form will still submit.

Here is the setup. You have a form and you’re trying to perform some sort of validation on it when the form is submitted and show the visitor some errors. You tie your validation to the form’s submit event using submit() and include event.preventDefault() good measure when any error occur. However, the form still submits even though errors are through, the event.preventDefault() does prevent the form from not submitting. Heck, you even throw in `return false` hoping the form won’t submit, but it still does.

The issue is that the form is being submitting via ajax and you can’t stop the ajax submission from happening through standard means. The only thing you can do is turn off ajax and submit the form yourself. Now in older versions of the framework, you could turn off ajax for form submissions separately, however in the latest version (1.1.0) you can only turn off ajax globally by setting `ajaxEnabled` to false. This sucks as you most likely want all the ajax goodness, just not on form submission.

The way around the is to add `data-ajax=”false”` to the form:

<form id=”myform” action=”somepage.html” method=”get” data-ajax=”false”>

The will prevent the form from being submitted via ajax. Now the fun part if how in the world are you going to submit the form data to the action page using ajax so you get that nice ajax spinner thingy when you’ve turn ajax off? The answer is manually submit the form data by serializing it and appending it to form’s action attribute. Then use `$.mobile.changePage()` to submit the data via ajax. Below is a little helper function I wrote to do this:

submitForm = function(formid){
var form = $(“#” + formid);
var page = [];
page.push(form.attr(‘action’));
page.push(form.serialize());
$.mobile.changePage(page.join(‘?’));
}

To use, just call submitForm(‘your form id’) and it will handle the submission for you:

submitForm(“myform”);

7) Calling trigger(‘create’) on date-role=”header” has no effect

Though you need to call trigger(‘create’) on the data-role=”content” when adding dynamic content for it to style properly, this doesn’t hold true for data-role=”header”. The solution is to call trigger(‘pagecreate’) instead.

————————–

I will continue to add to this post as more issues come up. Please let me know if you have any tips in the comments below.

CFIMAGE Error: Numbers of source Raster bands and source color space components do not match

Posted in ColdFusion by rip747 on March 30, 2012

You might get this error when trying to manipulate a photo with cfimage (such as resizing). I got this when trying to do exactly that with a JPEG.

In order to get around this error, I opened up the photo in a photo editing program and saved the photo as a BMP. Then I opened up the BMP in the photo editor and saved it as a JPEG.

Gotchas with LG Esteem and Titanium Development

Posted in Android by rip747 on February 21, 2012

1) you have to download the esteem driver from here:

http://androidinvasion.us/downloads/LG_Eseem_Drivers.msi

from http://androidinvasion.us/forum/index.php?topic=77.0

all other drivers i’ve found , even on the LG site, didn’t work.

 

Railo on IIS6 installation and configuration errors

Posted in CFWheels, ColdFusion, Railo by rip747 on October 17, 2011

railo is a great alternative to adobe’s cfml server, but there lets face it… it’s a pain in the ass to get configured on iis6! rather then have you fight through all these errors, i’ve documented the errors that not only i encountered during the setup, but also was able to create. hopefully this will save you from getting frustrated.

the following errors may happen when installing railo on IIS6 and visiting the site. (note: all paths assume that you installed railo to the c:\railo directory)

Error: Invalid function

Cause: This happens when you haven’t chosen to install the iis connector or something screwed up in the installation of the iis connector. you can see this if you go into the C:\railo\connector\isapi_redirect-1.2.31.properties and you see @@install_dir@@ in the file. those markers were suppose to be replaced with the directory you installed railo.

Fix: don’t just try to change these markers to the installation directory as they aren’t just in this file. the best bet is to run the installation again and make sure you check to install the iis connector.

Error: The system cannot find the path specified.

Cause: you forgot to configure the jakarta virtual directory for the site in iis.

Fix: go into iis and add a virtual directory called “jakarta” to the site experiencing the error. make sure to point it to the c:\railo\connector directory. Make sure to give the virtual directory “scripts and executables” permissions.

Error: You get prompted to download the cfm file

Cause: you forgot to give the jakarta virtual directory “scripts and executables” permissions.

Fix: give the jakarta virtual directory “scripts and executables” permissions.

Error: you get a 404, page not found error (from IIS)

Cause: you have not allowed unknown cgi and isapi extensions in IIS

Fix: click on the web server extenstions folder in iis admin. allow both unknown cgi extensions and unknown isapi extensions.

Cause: this could also be because the application extension aren’t configured for *.cfm extensions.

Fix: the railo installation instructions forgets to mention that you need to configure the site with application extensions for *.cfm extensions. go into the properties for the site and click the “home directory” tab. next click the “configuration” button next to where the execute permissions drop down is. on the next page, click the “add” button under the application extensions section. for the executable, browse to the  isapi_redirect dll located in the c:\railo\connector directory. for extension, enter in *.cfm. uncheck the “verify that file exists” checkbox. repeat this process for *.cfc if you site uses components.

PROTIP!!!!: if you want you can configure all the sites and future sites with these application extension by right clicking on the “web sites” folder and following the instructions above.

Error: you get a railo missinginclude error

Cause: you have configured the host section of server.xml wrong

Fix: most likely the cause is when you have misspelled an alias. make sure that all the aliases are spelled correctly and that the host section is configured properly.

Error: Unspecified error

Cause: you don’t have the isapi filter configured for your website.

Fix: the installation instructions for railo forget to mention that you need to configure an isapi filter for the website in order for railo to work. go into the properties of the site and click on the ispai filter tab. add a filter called “railo” and for the executable, point it to the isapi_redirect-X.dll located in the connector directory. so for 3.3.1 the path would be c:\railo\connector\isapi_redirect-1.2.31.dll.

Crystal Reports XIR2 not displaying PDF reports on Windows 2008 and IIS 7.x

Posted in TechSupport, Windows by rip747 on September 9, 2011

UPDATE: I’ve tightened up the permissions that the Windows\Temp directory needs. Seems that IIS_IUSRS requires Modify permission.

I’ve been tackling this problem for a few weeks now. We are in the process of consolidating servers at my work and moving them all to a Windows 2008 (32-bit) server running IIS 7. There is one app in particular that was giving us problems that was using Crystal Reports XIR2.

What was happening was that when Crystal was generating a report to PDF and pushing it to the browser, the browser would just keep working and nothing was getting displayed. This resulted in the dreaded “Load Report Failed” error in the application event log. Also if you looked in the Widows\Temp directory, you would see the *.rpt file would never get deleted. Seems that something was blocking not only the Crystal from generating the PDF, but also from deleting the *.rpt file that was generated.

After weeks of trying everything I could think of under the sun and even contacting Microsoft about this, I couldn’t get a solution. Needless to say I had to figure this out myself, which is exactly the type of problems I like since it brings me back to my administrator roots 😉

In order to finally get this working, I had started from scratch. I first reinstalled all the software that the old server had on it:

Crystal Reports XI Release 2 .Net 2005 Server

I tried pulling up the report again and total fail. Looking at the dates of the dlls in the “C:\Program Files\Business Objects\Common\3.5\bin” directory on both servers, I noticed that the dates of the files were different. The ones on the old server were from 2008 while the ones on the new one were from 2006. Looking at the list of installed programs on the old server, I could only see that “Crystal Reports XI release 2 .Net 2005 Server” was the only things installed, very strange.

I asked a co-worker of mine if we had the full version of Crystal Reports XI Release 2 laying around anywhere and it turned out we did. I figured that maybe by installing the full version along with all the service packs for it, the dlls on the new server would get updated. I next installed the following:

Crystal Reports XI Release 2
Crystal Reports XI R2 Service Pack 2
Crystal Reports XI R2 Service Pack 3
Crystal Reports XI R2 Service Pack 4

and for good measure:

BusinessObjects Enterprise XI Release 2 Service Pack 1

After installing the software, I checked the dlls and they were at the 2008 date! Awesome! Tried the app again and… Nothing 😦

At this point I figured that it had to be a permission issue since 95% of the problems you encounter with Windows 2008 are permission issues. I downloaded and ran ProcessMonitor on the server, filtering by “Process Name” and selecting “w3wp.exe” as the process. I cleared the events and started the capture.

After hitting the site and replicating the error again, I looked in the events that ProcessMonitor captured. I noticed that at the end, I was getting an “Access Denied” on the Windows\Temp folder. I remembered that sometimes you will need to give the “Network Service” user modify access to Windows\Temp folder if web applications are using it. After configuring the security on the Windows\Temp folder I tried again. I still got the same “Access Denied” error 😦

At this point I was stumped, until I realized that the site was configured to also use “ASP.Net Impersonation”. Maybe it wasn’t using the “Network Service” account but the credentials of the person hitting the site? For the heck of it, I gave “Everyone” full control on the Window\Temp directory. Tried the site again and… Success! The app worked.

Now that I’ve gotten through the problem, I’m going to dive more into it since I’m not liking the fact of having “Everyone” full control on the Windows\Temp directory, but at least everything is working.

So in summary, in order get through this issue, you will need to install the following software:

Crystal Reports XI Release 2 .Net 2005 Server
Crystal Reports XI Release 2
Crystal Reports XI R2 Service Pack 2
Crystal Reports XI R2 Service Pack 3
Crystal Reports XI R2 Service Pack 4
BusinessObjects Enterprise XI Release 2 Service Pack 1

and give the following permissions on the Windows\Temp directory:

IIS_IUSRS – Modify “Everyone” full control

If anyone else has had this problem and gotten through it, please tell me what you did to resolve this.

Syncing mobile devices with Exchange errors with: The certificate chain did not end in a trusted root

Posted in Exchange, TechSupport by rip747 on July 20, 2011

When trying to sync a mobile device or testing your Exchange configuration using testexchangeconnectivity.com you receive the following error:

“The certificate chain did not end in a trusted root. Root = OU=VeriSign Trust Network, OU=”(c) 1998 VeriSign, Inc. – For authorized use only”, OU=Class 3 Public Primary Certification Authority – G2, O=”VeriSign, Inc.”, C=US”

The problem is that a certificate in your certificate chain is untrusted. If you look at the OU it tells you what certificate is untrusted. Go to the certificate authority’s website to download and install the appropriate certificate.

NOTE: for the issue that I had with my Verisign certificate, I ran around in circles looking for the right cert to download. It is quite apparent that Verisign’s knowledge base search sucks. Only after calling their support department was I able to get the right information. That said article SO13347 in Verisign’s knowledgebase had the correct certificate to resolve this problem.

android.process.media force close

Posted in Android by rip747 on July 19, 2011

I’ve seen this all over the web and I’m a victim of it as well. What happened was I rooted my new LG Optimus S that I got when I switched over to MetroPCS. While uninstalling some of the bloatware that came with it, I removed the MetroWeb browser. I figured that since I installed Opera Mobile I didn’t need it. BIG mistake! Apparently the MetroWeb browser is so tied to the system that I couldn’t get the Android Market to install anything. Any attempt at downloading and installing an app would cause the dreaded andriod.process.media error.

Anyway, this is how I finally got around it. NOTE: this fix requires that you have root explorer 2.16 installed on your phone. If you don’t have it installed, you can download it from here.

First thing to do is you need a copy of the Browser.apk and Browser.odex from a working phone or download them from my box.net widget on this blog.

Next, hook up your android to your computer via a USB cable so you can access your sdcard and copy the two files to your sdcard.

Next, open root explorer and copy the Browser.apk and Browser.odex files from your sdcard to your /system/app directory on your phone. (be sure to toggle the Mount R/W button so your can copy the files).

NOW THE IMPORTANT PART! What you will need to do is to change the permissions and the owner for these two files.

Long hold on the Browser.apk file and select Permissions. Give Read, Write and Execute permissions to Owner, Group and Others. Basically you’re checking all 9 boxes. You don’t need to check any of the Special Permissions. Click “OK” when done.

Long hold again on the Browser.apk file and select “Change Owner”. Change the owner to “0 – root” for both Owner and Group. Click “OK” when done.

Toggle the “Mount R/O” button.

Power down your phone and then power it back up. If all goes well, you should see the MetroWeb app in your app listing.