Tuesday, November 29, 2011

Virtualbox - Mac Host - Ubuntu Guest - Networking

Messing with this half the day... It's so simple I overlooked it and went down strange Google paths.

This is the simple, straightforward answer to setting up networking for the Guest OS.

You set up two of the 4 possible network adapters before booting up the system. You can change the network settings while it's running and then run "sudo ifdown-a" and "sudo ifup-a", but that doesn't let you add a second adapter.

Set "Adapter 1" as "NAT" - this only gives the GUEST OS outside internet access through the HOST.

Set "Adapter 2" as "Host-only Adapter" - this only gives the HOST access to the

Together, we have what we want, we don't need anything fancy or custom, no bridgets, no scripts. But there is one tiny config setting that needs to be set to use the second adapter...


After you boot up the Ubuntu Linux server and log in you have to set up the second adapter in the interfaces config file because, by default, it only has one.

It will look like this:

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp


Now add this to the bottom:

# The primary network interface
auto eth1
iface eth1 inet dhcp

Now reboot.

Now when you run "ifconfig" you should see an ip address under "eth1". That is the IP address you can SSH to from the HOST machine.

YES!   IT'S REALLY THAT SIMPLE!


Saturday, November 26, 2011

Note to self: Railo Mail Server Gmail SMTP setup

When setting up the Railo Administrator Mail server to use Gmail, remember these settings so you don't waste time trying different arrangements:


Server (SMTP): smtp.gmail.com
Username: myaccount@gmail.com
Password: strongpassword
Port: 587
TLS: YES (checkbox checked)
SSL: NO (checkbox blank)


This link was somewhat helpful: http://mail.google.com/support/bin/answer.py?answer=13287


-Garrett

Sunday, November 20, 2011

MySQL to JSON - this is cool!

I've used MySQL's amazing "GROUP_CONCAT()" function many times, it's an absolute life saver in very specific situations, and it's supa-fast. I've attempted to use it to essentially store sub-query data in a string. This usually makes the resulting code less than ideal when attempting to parse the string back into an iterate-able data set. Today I needed this once again and I wasn't looking forward to it.

Recently I've dealt a lot more with JSON data sets with AJAX features and I've fallen in love with JSON. I love how universal it has become to pass data between programming languages, be that client side Javascript to/from server-side or between server-side languages in web services, whatever. It's always great. So I was thinking to my self, 'What if I could get by multidimensional data from the database into a JSON string?'. So I started googling "SQL to JSON" and I found this guys blog post: http://www.thomasfrank.se/mysql_to_json.html. (Thank you Tomas Frank! Wow, nearly 5 years ago. Ha!)  It was great. And all the comments were helpful as well. So I wrote my own in similar fashion. See my pseudo-sql below:

select f.fileid, f.parentfileid, f.filename, f.filesize, f.onloadon, f.uploadby, u.firstname, u.lastname,
    IFNULL((select CONCAT('[',
                    GROUP_CONCAT(
                        CONCAT('{"fileid":"', f2.fileid, '","filename":"', f2.filename, '","filesize":"', f2.filesize, '","onloadon":"', f2.onloadon, '","uploadby":"', f2.uploadby, '","firstname":"', u2.firstname, '","lastname":"', u2.lastname, '"}')
                    SEPARATOR ','),
                 ']')
            from filestable f2 LEFT OUTER JOIN userstable u2 ON u2.userid = f2.uploadby
            where f2.parentfileid = f.fileid
            and f2.deleted = 0
            order by f2.uploadon ASC),
    '[]')  as versions
from filestable f
  LEFT OUTER JOIN userstable u ON u.userid = f.uploadby
where f.parentfileid = 0
and f.deleted = 0


Essentially I'm querying for files and getting any past versions of each file packed into a JSON formatted string.

Then in the Coldfusion code you call: DeserializeJSON(myquery.versions) and you have an ARRAY of STRUCTURES in Coldfusion, each struct is a subquery row of data containing old file servsions. This is how we get 3 dimensional data from a 2 dimentional database query.

*** I hope the single and double quotes are easily readable in the code sample above. SQL strings are in single quotes and the JSON keys and values are all in double quotes.

*** It's important to notice the IFNULL() function around the sub-query because without that, if there are no records, it returns a NULL value. In Coldfusion that becomes an empty string. That's bad when we were expecting an array. I learned that the hard way when it was erroring out on my ArrayLen(variables.filevs) code, see below.

*** Another important note is to sort the sub-query Ascending by date. The reason for this specification is so that we can more easily loop over the array backwards to display the most recent versions at the top and the oldest at the bottom.

This is how the resulting Coldfusion code might look:

<cfloop query="variables.myquery">
    <!--- html here to display each file (current version) --->
    <cfset variables.filevs = DeserializeJSON(variables.myquery.versions) />
    <cfloop from="#ArrayLen(variables.filevs)#" to="1" step="-1" index="variables.LLfilev">
        <cfset variables.filevdata = variables.filevs[variables.LLfilev] />
        <!--- html here to display the data of each old-versions of each file --->
    </cfloop>
</cfloop>


Clean and simple. You've gotta love that. Fast too! Much better then getting all files, parent and old-versions, and then running a few query-of-query's in our server-side code to first get the parent records (current vertsions) and then get the old-versions with a query inside each loop. Without this, QoQ may have been the only solution. This new solution is *SO* much better, faster, and cleaner.


Friday, November 18, 2011

CFExecute with Multiple Bash Commands Inline && Getting the latest GIT short hash && custom CSS/JS caching solution - OH MY!

This one was hard. I knew it was possible so it was only a matter of time, googling, and testing. I got it.

Here is the code. Here I'm using the command "git rev-parse --short HEAD" to get the short hash of the latest GIT commit. But, in order for that to work we need to get into the right directory and CFExecute *starts* in the user directory of whatever user the Coldfusion server is running in. If you haven't set one the it's probably "/root".

So we first need to change directories to the current web root, then we grab the short GIT log hash, like this:

<cfexecute name="/bin/bash" arguments="-c 'cd -P #ExpandPath('/')#; git rev-parse --short HEAD'" variable="variables.test1" timeout="1" />

LOVE IT!

But a note on the results. If you output the above <cfoutput>[#ariables.test1#]</cfoutput> with brackets around it you will see there is an extra space on the end. That annoys me but I couldn't shake it off. My only solution was to trim itself afterwards with a <cfset variables.test1 = TRIM(variables.test1) />. Lame.

So, why am I wanting the latest short GIT log hash? I'm glad you asked.

I'm using it in my CSS and Javascript file tag query strings to prevent improper caching of old CSS and Javascript files so that users will always have the latest changes without having to clear their cache.

Example:

<link href="/css/global.css?v=<cfoutput>#server.codeversion#</cfoutput>" type="text/css" rel="stylesheet" />
<script src="/javascript/jquery.prod.min.js?v=<cfoutput>#server.codeversion#</cfoutput>"></script>



Yup. I LOVE IT!

Sunday, November 6, 2011

Railo Coldfusion & Less CSS (java implementation)

I just spent the last 4 hours figuring this out. I had to blog this to help someone - and my future self.

I wanted to start using Less and I want to compile it server side only when I need to. I have some url parameters, which can only be run from the admin login, that I use to reset certain caches and things. In this case I want it to recompile my less css only when I want to. So I need to set up a script to trigger and run the less css compiler. Railo is the BEST server wide web engine and it can tap into java like it's butter. I discovered that java has a server-side javascript engine called Rhino. A lot of trendy groups are there are implementing server-side javascript. I don't tend to get trendy, but I love the idea for very specific application uses. Anyway. With this Rhino we can implement the original Less.js compiler server-side. Sweet! Not so fast... People have tried to do this with Coldfusion and I can't get them to work (4 hours worth of attempts).

I finally figure out my own implementation - thanks to railo's native java loader - TWO LINES OF CODE!!!

<cfset variables.javajs = createObject("java","org.mozilla.javascript.tools.shell.Main","/jars/js.jar")>
<cfset variables.javaless = createObject("java","com.asual.lesscss.LessEngine","/jars/lesscss-engine-1.1.4.jar")>

I'm going to try to retrace my steps...

From https://github.com/cloudhead/less.js you can get the source and compile your own. Or you can use what thus guy put together http://www.asual.com/blog/lesscss/2009/11/05/less-for-java.html. That's what I did. Here is his Git repo: https://github.com/asual/lesscss-engine.

Actually, that's not right, I got it from this guys presentation notes here: http://dopefly.com/techblog/entry.cfm?entry=359
direct link: https://github.com/NathanStrutz/Write-LESS-CSS-Presentation-Material. That's where I got the "lesscss-engine-1.1.4.jar".

From even with the "js.jar" and the "lesscss-engine-1.1.4.jar" I couldn't get things to work. I had forgotten my Java schooling.

I hate the javaloader.JavaLoader crap. And it's old school. Railo can do it - natively. But I could scratch *how*. I googled and googled and I always thoguht it would be so simple. I finally googled and found the class to invoke. Railo's example code only gives you this:

<cfset object = createObject('java','path.to.package.classtoinvoke','/path/to/jar/file/on/system')>

and that didn't give me the name of the 'class to invoke'. But the Rhino site 'http://www.mozilla.org/rhino/scriptjava.html' did. And then from the code samples from Nathan Strutz presentation notes sample code I got the "com.asual.lesscss.LessEngine" class name for the 'js.jar'.


So now we're in business!

Here's how to compile the styles.less code into styles.css:

<!--- get your source styles.less from a cffile read or from in string, whatever, in a variable, say, 'variables.lessSource' --->
<cfset variables.outputcss = variables.javaless.compile(variables.lessSource) />
<!--- Then output the 'variables.outputcss' into <style></style> tags or do a cffile write to styles.css file and link the in the css file --->

That's it.



While I'm writing all this I get some other thoughts. You might even be able to pass in a source file path and write it right back to a cffile write -- but I haven't tested that yet. But in theory, maybe like this:

<cffile action="write" file="/path/to/css/styles.css" output="#variables.javaless.compile('/path/to/source/styles.less')#" />

UPDATE:
The above didn't work because it's expecting a java type file stream. This works:
<cffile action="write" file="#expandPath('/')#cssjs/test.css" output="#variables.javaless.compile(CreateObject("java", "java.io.File").init("#expandPath('/')#cssjs/less/test.less"))#" />

That would be slick - but again, just a theory, untested.

Now, while trying to retrace by steps over the last 4 hours I also discovered from a final note from the dopyfly.com blog post mentioned above that there is a low level C implementation of the LESS compiler int he git repo, "lessc". There might had been a simpler implementation via the cfexecute tag to process styles.less files into styles.css files. I'll give that try another day.

UPDATE:
This is way more complicated than I expected. It requires nodejs to be installed. I actually tried it and ran into dependency issues. If someone gets this command line lessc to work on ubuntu command line, please drop a comment.


That's a nice wrap! From bloated implementations with tricky dependancies I got it down to three lines of code! Haha!
Here it is again (excluding code to get the less source and write the output css file):

<cfset variables.javajs = createObject("java","org.mozilla.javascript.tools.shell.Main","/jars/js.jar")>
<cfset variables.javaless = createObject("java","com.asual.lesscss.LessEngine","/jars/lesscss-engine-1.1.4.jar")>
<cfset variables.outputcss = variables.javaless.compile(variables.lessSource) />


This is proof of concept which I have working successfully.