Your (The Reader's) Privacy

February 6, 2014 4:02 pm

As I mentioned in an earlier post, one of my goals in moving to a self-hosted blogging platform was to protect the privacy of my readers.  WordPress, by default, has a few tendrils that slither out across the Internet and violate that privacy letting any number of 3rd-party websites track your movements across the web.

By default it: loads special fonts from Google's servers; uses the Gravatar service to show an image next to your name if you leave a comment; sends your email address and other data off to a third party to run heuristics as part of the bundled anti-spam tool.

I've excised my installation of these issues.  When you load this blog I do not enable any other services to track your movements.

Instead of using the bundled anti-spam tool, Akismet, which sends your data to a 3rd party, I'm using some less powerful, but locally controlled, methods that include things like a simple checkbox on the comment page to confirm you're not a spam bot.  These more primitive methods of fighting spam would probably not work for a high traffic site (thus high value target), but will probably be just fine for us.

You may have noticed the social media sharing buttons at the top of each post.  Normally this would allow each of those services to track your visit to this site.  But these buttons are a little different than what you're probably used to.

These buttons require two clicks to work.  One click activates the button and connects to the associated social media service (which in turns means that they are now able to track your visit to this site).  A second click does the normally expected behavior for sharing something to that service.  This privacy-protecting method of enabling social media sharing is powered by the Social Share Privacy project.  The project is still a little rough around the edges, but it does work (though it took me longer than I expected to configure).

The final piece that I'm working on is migrating all the old media to my server.  Currently the pictures and videos in old posts are still hosted on Blogger's (a.k.a., Google's) servers.  I'm slowly working through bringing those files to my server so that you don't need to interact with any 3rd party to visit this blog.

Also, if you really like, you're free to visit this site using an encrypted (https) connection.  However, at the moment I'm still using a self-signed certificate (so your browser will warn you that it's not secure, just add an exception).  It's a lie to say it's not secure, what it really means is that I just haven't paid one of the certificate companies to verify my identity.  The connection will still be encrypted as any other.  If you really care I'd be happy to take your phone call and verify that the certificate your browser sees is in fact the one I created.

"Homeland"

10:28 am

I was casually reading this Consumerist story and the use of the word "homeland" was kind of disturbing.  Even after more than 10 years, "homeland" still has a disturbing, big-brothery, propaganda-y, dystopian-ness to it.  Maybe "even after" is the wrong phrase, maybe it is exactly due to how it has been used over the last decade that gives it the same, if not more of an, overtone of unpleasantness, of wrongness, even sinisterness.

The usage was a quote from some unnamed "senior U.S. official" in this form:

While we are not aware of a specific threat to the homeland at this time, this routine communication is an important part of our commitment to making sure we meet that priority...

I just can't read that sentence without "homeland" pricking me deep in my psyche and bothering me deeply.

The whole thing bothers me.  Someone "official" telling everyone that they should be afraid not for any particular reason ("not aware of a specific threat"), but just because they want you to remember you're supposed to be afraid or something.

I dislike what we did to our country after September 11, 2001.  Terrorists killed a few thousand people; tragic--but an absolute pittance compared to car accidents (33,000 per year), heart disease (600,000 per year), and suicide (38,000 per year).  Terrorists killed a few thousand people in 2001, but we've been terrorizing ourselves for over 12 years.  We pushed an agenda of fear and allowed that agenda to either erode or destroy founding ideals of liberty and freedom.

I'm hoping we can begin to change that; but quotes like this one seem to have no purpose other than to continue pushing an agenda of fear-mongering.

I'm hoping we can begin to change that because of articles like this one from Ars Technica discussing that one of the authors of the PATRIOT Act is trying to undo some of the damage he's done and reign in some of these activities (not that he admits this is his fault in any way, of course).  It is just really sad that these people were not listening 10 years ago when others were warning how dangerous these laws would be.

Criteria Aggregator: Dynamic Criteria Queries in Grails

February 5, 2014 2:42 pm

A few years ago I wrote about dynamically building criteria queries in Grails.  Well the use case we had disappeared and I didn't do much of anything with dynamic criteria queries until recently.  As I've mentioned in an update on that post, you probably just want to use DetachedCriteria now instead of taking this route, but DetachedCriteria don't support the same range of functionality that normal criteria queries do.

I ran into this limitation when I needed to use subqueries which DetachedCriteria do not support but standard criteria queries do.  After spending hours trying to work around the limitation and still use DetachedCriteria I decided to give up and create a nice way of using the dynamic criteria queries based on my past experience, the comments on that post, and my greatly enlarged knowledge of Grails.

So I created a nice clean class called "CriteriaAggregator":

package org.example.package
import grails.orm.HibernateCriteriaBuilder

// Aggregate query criteria for a Domain Class
// Example: def qa = new CriteriaAggregator(MyDomainClass)
//    qa.addCriteria { idEq(12345L) }
//     def results = qa.get()
public class CriteriaAggregator {
    private Class forClass
    private List<Closure> criteriaClosures

    // forClass should be a Grails DomainClass; but since Grails injects rather than inherits I can't specify the type better than "Class"
    public CriteriaAggregator(Class forClass) {this.forClass = forClass; criteriaClosures = new ArrayList<Closure>(10)}

    // criteriaClosure is the exact same type of closure you'd pass to DomainClass.withCriteria(criteriaClosure)
    public void addCriteria(Closure criteriaClosure) {criteriaClosures << criteriaClosure}

    public long count() {return runQuery('get') {projections {rowCount()}}}
    public def get(Closure additionalCriteria=null) {return runQuery('get', additionalCriteria)} // Query must return only a single row
    public def list(Closure additionalCriteria=null) {return runQuery('list', additionalCriteria)}

    private def runQuery(String method, Closure additionalCriteria=null) {
        HibernateCriteriaBuilder criteriaBuilder = forClass.createCriteria()
        def critClosures = criteriaClosures // Bizarre that criteriaClosures won't evaluate properly inside the "$method" closure, but it won't so this works around that issue
        criteriaBuilder."$method" {
            critClosures.each{closure -> closure.delegate = criteriaBuilder; closure()}
            if (additionalCriteria) {additionalCriteria.delegate = criteriaBuilder; additionalCriteria()}
        }
    }
}

This wraps and defers the creation of the normal criteria builder allowing you to build up the criteria dynamically and execute it when desired.

Suppose you had a Customer domain class with many Orders.  Orders have a date, paymentMethod, and totalPrice.

def customerQueryAggregator = new CriteriaAggregator(Customer)
customerQueryAggregator.addCriteria {
  orders {
    def now = new Date()
    between('date', now-7, now)
  }
}
customerQueryAggregator.addCriteria {
  orders {
    eq('paymentMethod', 'cash')
  }
}

def numCustomersInPastWeekPayingCash = customerQueryAggregator.count()
println numCustomersInPastWeekPayingCash

def highRollersInPastWeek = customerQueryAggregator.list{
  orders {
    gt('totalPrice', 50000)
  }
}
println highRollersInPastWeek

This is obviously a trivial example where you don't need to use the aggregator.  But it's just to illustrate the usage.  I'm using it to build up a query based on a set of options provided by a caller as part of a reusable and flexible service.

Using this I can handle subqueries like so:

import grails.gorm.DetachedCriteria as GrailsDetachedCriteria
import org.hibernate.criterion.Subqueries
import grails.orm.HibernateCriteriaBuilder

def customerQueryAggregator = new CriteriaAggregator(Customer)

GrailsDetachedCriteria largeOrderSubquery = new GrailsDetachedCriteria(Order).build {
  eqProperty 'order.id', 'this.id'
  gt 'totalPrice', 50000
  projections {property 'id'}
}

customerQueryAggregator.addCriteria {
  add(Subqueries.exists(HibernateCriteriaBuilder.getHibernateDetachedCriteria(largeOrderSubquery)))
}

Update April 4, 2014:

I ended up having some trouble with the proper definition of table aliases (it always wanted to call "order" "this" even though we already had a "this") while handling the GrailsDetachedCriteria subqueries.  To work around it I ended up dropping back to straight Hibernate, but it still works with the CriteriaAggregator.

import org.hibernate.criterion.DetachedCriteria as HibernateDetachedCriteria
import org.hibernate.criterion.Restrictions
import org.hibernate.criterion.Disjunction
import org.hibernate.criterion.Subqueries
import org.hibernate.criterion.Projections

def customerQueryAggregator = new CriteriaAggregator(Customer)

HibnerateDetachedCriteria largeOrderSubquery = new HibernateDetachedCriteria.forClass(Order.class, 'order')
largeOrderSubquery.add(Restrictions.eqProperty('order.id', 'this.id'))
largeOrderSubquery.add(Restrictions.gt('order.totalPrice', 50000))
largeOrderSubquery.setProjection(Projections.property('order.id'))

customerQueryAggregator.addCriteria {
  add(Subqueries.exists(largeOrderSubquery))
}

My Custom Charging Box

February 2, 2014 9:31 pm

I decided to be crafty.  I had an idea for a decent looking box from which to charge gadgets.  I finally found a box I liked (a cigar box, as it turns out).  And then we went off to Jo-Ann Fabrics for other materials (Josh, if you're reading this, I was reminiscing of our Jo-Ann Fabrics trips back in the day).

I was looking in the upholstery fabric section, but not finding anything smaller than about 10 feet long.  I did see some options in the remnants of some suede that would probably have worked.  But then Jess stumbled upon some swatches of leather on the other side of the store which were perfectly sized.  They also had a strap of leather that gave me an additional idea to give it an old strapped trunk sort of look.

You'll quickly see that I'm not exactly a fine craftsman, but it came out well enough and I only threated to give up 3 or 4 times (me and reality don't get along so well; my job has "undo").  It was kind of fun and now it cleans up the mess of charging cords that normally are strewn about the house and kitchen counters.

Nifty Fifty - Pentax smc DA 50mm f/1.8

8:26 pm

I finally got a "nifty fifty" lens, the Pentax smc DA 50mm f/1.8.  I've been busy getting this new home for the blog up and running and haven't had much of a chance to play with it yet.  But I did, of course, take a couple test shots when it arrived earlier this week.

Prime 50mm lenses are often referred to as "nifty fifties."  The name apparently stems from the Canon EF  50mm f/1.8 II which earned the title for being affordable and still having good optical qualities.  The nickname has leaked out to pretty much any manufacturer's 50mm lens that maintains good optics while hitting an affordable price point.  My understanding is that since the 50mm lens has long been a staple of the industry pretty much every manufacturer has a "nifty fifty."

The Pentax smc DA 50mm f/1.8 definitely earns this title.  I picked it up new for just under $200 (I'd been waiting months for a good price) and the image quality is fantastic with great depth of field control.

Here's the first test shot I took:

Pentax 50mm f/2.0 test shot
50mm prime, f/2.0, ISO 2500, 1/60s

The sharpness is quite good and the depth of field is very slim (at f/2.0 and a short object-distance).  I look forward to playing with this lens more.