I like the free, hosted wordpress.com site I have, but I need something a bit more customizable. Therefore, I’ll probably be pretty silent over the next couple of days while I upgrade my WordPress to a real install on my own hosting account. But don’t worry, I’ll be back
Latest Entries »
In my last post on the subject of apologetics, I argued the true spirit of apologetics should be focused on laying out the place of Christian beliefs within the context of the life and community of faith. Instead of trying to “convince” non-believers about the “reasonableness” of the historicity or phenomenology of some point of doctrine, I suggested that the “reasonableness” of Christian belief can only be fully realized in the articulation of these doctrines as emerging from the experience of the faithful themselves. In this way, then, beliefs about the Incarnation, resurrection, etc. are not “truths” that necessarily exist independently of the profession of faith of the community of believers, but rather find their truthfulness and meaningfulness from the mission and identity of the body of Christ within the kingdom of God in the world.
I suggest that the purpose of apologetics was never intended to be about converting others to one’s way of thinking through logic and argumentation. Rather, to recall the famous Petrine passage, Christians are to give an answer “…to everyone who asks you to give the reason for the hope that you have” (I Peter 3:15). The words in bold are important, for they frame the course that apologetics are to take. The “answer” we are to give is fundamentally about the hope we have placed in Christ through the existential committing of our entire selves to the purposes of the kingdom of God through the act and life of faith. And since the hope we have is rooted irrevocably within this faith, it is not something that can be principally about the utilization of logic and reason to bring about a change of mind and philosophical orientation in those who raise the questions.
The Theistic Argument
A perfect example of this is the question of the existence of God. In popular apologetics, the “question of God” is one that has taken form in a variety of answers across the centuries. From Paul’s argument in the Areopagus, to Anselm of Canterbury’s ontological argument, to the more recent Kalam cosmological argument supported by William Lane Craig, Christian theologians have made innumerable attempts to ground the “reasonableness” of theism in human logic, to widely varying degrees of success. Given that we are still asking the questions and coming up with new answers, it’s clear that none of them have been answered satisfactorily.
But these arguments’ lack of success and “staying power” is not because they haven’t employed logic sufficiently. To the contrary, I would argue it is simply because human logic is too limited to establish any argument about God in absolute certainty. As human epistemology is necessarily boundary-limited by the parameters of the universe, logic is only capable of dealing with those things that pertain to the same domain. As God is conceived of as “other-than” and “transcendent-of” the universe, the inability of human logic to apprehend the eternal nature of the divine is something that cannot be overcome by the same domain-limited logic.
This is not the most important point, though. For even if one were to assume that logic is capable of exhaustively establishing the existence of God, what is gained from the perspective of apologetics?
The Outcome of a “Logical” Argument for Theism
To take a contemporary example, there are many who find promising avenues in the teleological argument for the existence of God, “proofs” which attempt to establish the nature and ontology of God on the basis of analyzing the “design” and history of the universe. As scientists gain more and more data about the universe, there is increasing openness within some circles to the idea that the universe is somehow “ordered” by an intelligent creator, or at least grounded in some trans-universal rational principle. However, regardless of how seemingly convincing these arguments “from design” might be, their establishment does not de facto lead one to Christian faith, as if the “proof” of the idea of God on the basis of the ordered-ness of the universe encapsulates the Christian understanding of God. There are many, like the British-born physicist Paul Davies, who are open to elements of the idea of theism because of the seeming force of the “rational” base of the universe. Yet this openness to the idea of “God” or even, in Davies’ words, a “rational ground in which the whole scientific enterprise is rooted…a universe…with meaning or purpose underpinning it,” does not translate into “faith” or really anything remotely resembling it.
And here we come to the crux of the issue. As I’ve been arguing, apologetics for Christian belief, for the vitality of the “content” of faith, is not something that can be established on the basis of human logic or any manner of phenomenological proof. Moreover, I would suggest that Christians should be somewhat restrained in their attempts to do such things. After all, to a Christian, the question of God’s existence is not one of logic or proof. The force of theism within Christian belief does not derive from a “logically necessity” that the universe had to have a “first cause” (or any other ontological/teleological/cosmological argument). No, the meaningfulness of God’s existence is rooted in the revelation of Godself in the person of Christ. This is the foundation for Christian faith not only in relation to the idea of the existence of a Creator, but also for how we think and theologize about God. In this way, then, from the perspective of faith, all arguments for the existence of God are made ex post facto; Christians do not (or should not, at least) argue from the existence of God to the revelation of God in Christ; rather, the very revelation of Godself in Christ is the basis for how we approach understanding the nature and existence of God. Apart from this unique understanding, the existence of God based on logical proofs does not begin to approach the meaningfulness of “God” within the complex of Christian belief.
The Crisis of Faith
Yet despite this seemingly self-evident conclusion, we find within popular apologetics a tendency to transform the very nature of faith into an act of intellectualism. The “proofs” for this or that doctrine are offered up, not simply to convince antagonists of the “truth” of Christian belief, but also to provide a measure of surety to its professors that the content of their belief is ultimately logical and rational, that their “faith” is something demonstrable and provable on the basis of whatever philosophical worldview holds sway.
While those who do this are, I assume, well-intentioned, such an approach to apologetics, in my view, does irrevocable damage to the place of faith within the dynamic of Christian life and belief. As mentioned before, the very nature of faith is that of crisis. It is the call to commit one’s entire ontology–life, energy, soul, body, desires,etc.–to the sovereignty of a God whose existence cannot be encapsulated nor demonstrated on the basis of human logic and reason. It is a call for the whole of one’s person to commit to a way of being that is “other-than” the patterns and paradigms of default human existence. Such a call, such a life, is not something that can be entered into casually or partially. To borrow the famous metaphor from Kierkegaard, faith is the total existential “leap” in which we abandon entirely our claims to ourselves and our abilities to “make” (understand, control, objectify) reality. In this ultimate resignation, we commit ourselves rather to the unknowable darkness into which we leap, a darkness which is illuminated with divine light only after the plunge has been taken.
But if this is the true nature of faith, a life characterized by sheer existential crisis and the fundamental disavowal of any human ability to apprehend “truth” on the basis of its own powers, we see that attempts to integrate the fundamental nature of faith into the very paradigms that have been disavowed is ultimately self-destructive. In “establishing” the articles of faith on the basis of logic, experimentation, historicity, and whatever other philosophical categories might hold sway, we ultimately emasculate faith, for it is no longer the wild, untamable force of crisis, but rather the comfortable conclusion of a ultimately self-justifying and self-deluding epistemology.
Is this Anti-Intellectualism?
So does this reorientation to faith-as-crisis mean that logic and reason in the articulation of belief are unimportant? Is the life of faith essentially a call to anti-intellecutualism? I would argue no, on both counts.
As I’ve stressed before, apologetics still has a very important role in the life of the Christian community. My suggestion is simply that rather than utilizing logical, rational arguments to try to convince non-believers of the “rationality” of Christian belief over and against whatever-other-beliefs, the target of apologetics should be to articulate the place which Christian beliefs have in the life and faith of the believer. So in the case of the idea of God, apologetics should not be about trying to use the power of sheer logic to convert non-theists to the acceptance of the idea of God (“Christian” or otherwise), but to rather lay out in an orderly and consistent way the place that theism has in the matrix of Christian belief, and how this article of faith informs the way Christians think about life, relationships, redemption, eternity, etc. For questions of “origins,” we should be less interested in trying to scientifically (or psuedo-scientifically) establish particular interpretations of an ancient creation narrative, but should concentrate on allowing the meaning of this narrative to inform our understanding of God’s purposes and designs for creation and our place in bringing this to fruition. And the list goes on and on…
If Christians are perceived as “anti-intellectual”, it is, I think, because so many have bought into the false paradigms of popular apologetics. Within these approaches, logic and reason are ends in themselves, so in many cases the expression of Christian belief is forced into an artificial antithesis of other “logical” arguments. So whether one is speaking of origins, theism, sexuality, etc., many “Christian” conclusions can come off as “stupid” and “anti-intellectual”, not because the actual categories of faith are devoid of rational force, but simply because a flawed methodology has led to an equally flawed articulation.
But as we’ve seen, this is wholly unnecessary. If we are truly about the work of apolgetics, we’d spend less time screaming and fighting trying to get non-believers to view “faith” as rational, and commit our energies to making sure that we have sufficiently articulated the meaning and place of Christian belief within the life of faith for ourselves. After all, until we have come to grips with the crisis of faith and the place of Christian belief within it, we will never be “ready to give a reason for the hope that we have.”
Ran into this issue today. At work, data returned from CFCs have a bunch of content pre-pended. In regular tag-flow coding, this is super-simple to overcome:
<cfcontent type="text/plain" reset="true" /> <cfreturn mycontent />
Using the cfcontent tag, I can “[discard] output that precedes call to cfcontent” (from the docs
). This strips out all the garbage that I don’t want, and returns only the awesome data that I need.
Since we’re getting ready to upgrade to CF9, however, I’ve been playing around with writing my ColdFusion components in the new 100% script-based syntax. One problem, though: there is no cfscript version of cfcontent, so I’m back to the original problem.
Fortunately, there is a solution. By tapping into the underlying Java methods that are exposed, we can easily recreate similar functionality. Here’s all it takes:
remote any function getdata() {
getpagecontext().getcfoutput().clearall();
return supersweetdata;
}
Nothing to it. And for future reference, take 5 minutes to dump out getpagecontext(). You can see all the nice methods that are available…who knows, you might just find something useful
For about 4 years now, I have had a premium membership with Napster (no, not the Napster that you remember from college…:)). My $15-odd dollars a month granted me access to millions of songs that I could stream over the internet, or download for quicker playback on up to 3 personal computers. Additionally, I could sync tracks to an MP3 player (up to 3 of them), allowing me to take my music on the road…it only required an annoying license-refresher-sync every month or so.
This worked pretty well for me for a long time. I was too cheap to buy an iPod, , so the 5GB (?) Creative Zen that I mooched off my little brother was the perfect fit. Then it broke (sorry Jared). And then Vista started hating the Napster software. And then all my favorite songs started showing up as only available in 30-second clips. And then I got my iPhone which, of course, isn’t compatible with most of ANYTHING that Napster does. It was time for a change.
So the other night I came across on article on Mashable about the launch of a brand-spanking-new app, a gateway app to the MOG music service.
Well, this was the first I had ever heard of MOG, so I decided to check it out. After quickly glancing at the features it offers, I was hooked. I dumped Napster and signed up. Here’s what I get for $10 a month:
- Commercial-free streaming of songs that I pick, not the garbage that Pandora thinks I will like (when I enter “Kenny Rogers” I DO NOT want to hear Kenny Chesney!!!)
- Songs are downloadable to your iPhone/Pod/Pad/Droid, so you can take them offline with you.
- If you feel lucky, you can select a custom ratio of “play the artist that I told you to” to “okay, play some artists that might be similar”
- You can “favorite” songs for easy playback if you don’t feel like downloading them
- Sweet 256Kbps playback…very nice
The one downside of this service is that currently the iPhone app is only enabled in iOS4 to deliver high-res album cover art. So no multi-tasking, but high-res album art? That’s some misplaced priorities. However, I trust that this will be remedied soon. Once this major oversight is cleared up, it is quite unlikely that I’ll ever be bothered by Pandora’s annoying ads ever again.
If you’re on MOG, or just bored, look me up
Recently, I’ve been visiting a variety of apologetics-focused blogs and forums (super exiting, right?
). During my readings and interactions with the bloggers associated with these sites, I’ve started asking some hard questions about the usefulness of apologetics within the life of faith and mission or the Church.
Given my background (B.S., Pastoral Ministries, M.A. Theological Studies), I’m definitely no stranger to the “logic” of apologetics. Based on the famous Petrine passage, the ultimate purpose of apologetics, as a discipline, is to “give an answer to everyone who asks you to give the reason for the hope that you have” (I Peter 3:15). From 2nd century Justin Martyr’s Apologies, to McDowell’s famous Evidence That Demands A Verdict, to Strobel’s Case for Christ, there is a long, varied, and rich tradition of apologetics within Christian theology. While motivations and level of expertise have varied in the execution, the ultimate goal of each work has been, I think, to show the Christian faith as something “reasonable,” to defend the faith on intellectual grounds.
While this is in itself a noble goal, I think something that is far too often overlooked is the interplay of philosophy, theology and biblical interpretation that happens between the apologist and doctrines they attempt to defend. That is, the doctrines defended in apologetics are never espoused in a vacuum; to the the contrary, the apologist brings a particular (or several, perhaps) philosophical orientation to bear upon not only the fundamental assumptions which drive the apology, but also upon the interpretations drawn from Scripture and the final form of articulation of the doctrine. From Justin Martyr’s Middle-Platonism to McDowell’s Evangelicalism, the content of the apologies are not philosophically neutral; rather, each and every apologist utilizes particular philosophical assumptions to support and articulate what they understand to the be the “reasonableness” of their position.
This, of course, begs an important question: if the field of apologetics is necessarily beholden–at least in part–to the philosophical orientation of the apologists, how does one go about separating the theological doctrine being defended from the philosophical assumptions upon which it is based? And is it possible.that there are particular philosophical assumptions that can, in fact, create artificial apologies apart from which one would be hard-pressed to otherwise defend a doctrine?
An Example: The Resurrection
In popularized apologetics, you’ll find literally millions of arguments about the “truth” of the resurrection. What almost all of these have in common, however, is that they focus primarily on the phenomenology of the resurrection, or more accurately, on the death of Christ, the emptiness of his tomb, and the historicity of the apostle’s claims about the same. In all honesty, I think if you look at these arguments with a more-or-less open mind (yeah, define that!), it’s pretty easy to conclude that it is “reasonable” to assert that there are good reasons to believe that Jesus’ tomb was empty following his crucifixion.
Ah! But wait. Most of the popular apologetics surrounding the resurrection of Christ seem to have very little to do with the articulation of the doctrine of resurrection, and have most everything to do with providing an historically reasonable basis for believing that Jesus was crucified, that his tomb was empty, and that his disciples believed that the reason for the emptiness of the tomb could be resolved in the idea of “resurrection.”
In these apologies, then, the veracity of the resurrection is subordinated to the relative salience of the phenomenological, historical, and psychological arguments. That is, it is proposed, or perhaps tacitly assumed, that the establishment of these de facto proves the reasonableness of the resurrection (which is actually still undefined within the apology). So what’s the problem with this? To get at the answer, let’s first take a peek at some of the underlying assumptions driving popular apologetic arguments for the resurrection.
Taking their cue from the emergence of modern objectivism, the methodologies of popular apologetics attempt to establish the reasonableness of particular theological doctrines on the basis of verifiability and proof. In other words, the working assumption of these approaches is that if tangible evidence (an empty tomb, for example) can be found and shown to align with a particular theological doctrine (the resurrection), then on an inductive and methodological level, the truth of the assertion (e.g., “Jesus was raised from the dead”) has been “proven” and “demonstrated.”
And even if the historical events in question cannot be immediately accessed, the argument is cast in such a way as to create a virtual laboratory in which the phenomenology and historicity of the ideas can be tested (and, ostensibly, “proven”). So in the case of the resurrection, even though the tangible proof of the resurrection (an empty tomb) cannot be presently demonstrated, other corroborating evidences are brought to bear upon the question. Although we don’t know where Jesus’ tomb actually was in order to verify that it is empty, other “proofs” such as the testimony of other historical witnesses about Christ’s death; the psychological orientation of the disciples; and their persecution as a result of assertions about Christ’s resurrection are cited as a round-about way of inductively establishing the proof of the assertion of Christ’s resurrection. The numbers are crunched, the test cases are run, and the result is a spit out the other end–we now have what is assumed to be an “objective” estimate of the relative probability of “X” having happened.
Let us imagine, for a moment, that such a methodology is bullet-proof.. Considerations of methodological propriety aside, what have we proven to have a high probability of actuality?
- That Christ was crucified? Yes.
- That Christ’ tomb was empty? Sure.
- That the disciples believe Christ was “raised from the dead”? Ok.
- That Christ was resurrected? No.
But wait a minute. If we’ve proven with a high degree of probability that 1-3 “happened,” why not 4? Why can we not equally assert the “reasonableness” of the resurrection on the basis of the establishment of these other points?
The reason is simple. We haven’t even defined the resurrection.
“But hold on,” you might say, “we have defined the resurrection: Christ’ tomb was empty.”
Is that really the definition of resurrection?
“Ok,” you might add, “it’s about the empty tomb and Jesus being raised to life. That’s what the disciples preached, after all.”
This is perhaps getting closer. However, if we continue to flesh out our theological understanding of resurrection, we find that we quickly move away from the phenomenological/historical/psychological criteria that we employed earlier. When we begin speaking of Christ’s resurrection, we rapidly run out of categories to define it.
The Problem of Methodology and Definition
And we see as much in the Scriptures. As you read the accounts of Christ’s resurrection and the experiences of people who encountered Christ after this spectacular event, you can feel the Gospel writers grasping for words to describe this new, un-real reality which is unfolding before them. We find descriptions of Christ veiling himself from his closest friends, appearing through walls, even “ascending” to heaven. This is not simply the “comfortable” language of “spirit”, but a boundary-limited vocabulary that is struggling to apprehend the profundity of the intersection of something completely super-natural with the mundane, the participation of creation in the fullness of very God.
So if this is our actual understanding of resurrection (the reality-altering intersection of Godself in the recreation of God’s creation), what are we doing with our apologetics? Why is so much emphasis placed on the historicity of the crucifixion and the psychology of the disciples?
Maybe a Different Way to Think about This
In thinking on this topic, I wonder if apologetics might not be more productive if we let off with trying so hard to “establish” particular “facts” (e..g, empty tomb, young universe, whatever) and spent our energies trying to better articulate the most meaningful parts of what we believe. After all, the resurrection is not ultimately meaningful in Christian theology simply because Jesus’ tomb is empty. Rather, it is meaningful because it expresses an explicit and profoundly theological understanding of the relationship between God and creation, and within itself encapsulates the unique Christian hope for the restoration of all things in God as we are brought to partake in the newness of eternal life–the con-mingling of the divine nature and creation–that God has granted to Christ in resurrection.
And the bottom line is this: no matter how “compelling” our historical/phenomenological/psychological arguments may be, the doctrine of the resurrection can NEVER be established absolutely on the basis of these analyses. This is not, of course, because it “didn’t happen,” but rather because what “happened” is entirely beyond the categories of any philosophical methodology that we would seek–consciously or otherwise–to bring to bear upon it; there simply exists no means of measurement for establishing whether or not it “happened”, much less what it fully means.
This, ultimately, is the crux of the issue. Certain apologetic methodologies may believe themselves capable of providing compelling, indeductive arguments for theological realities on the basis of material proofs. And to some, this may be sufficient to declare a particular belief to be “reasonable.” But ultimately, such epistemological causality cannot be forced. Thousands of people acknowledge that Christ was crucified and that the disciples believed him to have been resurrected (the empty tomb). Yet these same cannot, or rather, will not embrace the truth of the resurrection. Is it because there is not sufficient “proof” for Christ’s resurrection, the empty tomb, or the disciple’s belief? Would these same antagonists be convinced if there was simply “better” evidence? I don’t think so. Rather, the doctrine is rejected by many because the doctrine of resurrection inevitably calls each person to an existential crisis of faith, the committing of their entire person to the mystery of the divine purposes within creation and eternity. This “leap” is not something that can be softened or diminished by any amount of “evidence,” regardless of how compelling it may seem to be.
So what of apologetics? What is the goal of making the truths of faith “reasonable” to a world that is entirely alien to an understanding of faith? I think that it is less about trying to amass “evidence” for historical events and should be more about articulating the place which particular theological doctrines have within the domain of faith. The notion of “resurrection” will NEVER be reasonable to human epistemology, for it is something which smashes all the categories by which we understand ourselves and our place within the universe. But I think it is possible to nevertheless articulate the peculiar, and inextricable place which resurrection has in the life of faith. After all, the truth and beauty of resurrection lie not simply in the historical phenomenon of Jesus’ empty tomb, but in the reality of the newness of life which Christ was granted by the Father. The doctrine of resurrection is crucial to Christian theology, for it challenges that death is not the final chapter in our story, but that we, like Christ, can partake of the divine life of the Father in a renewed way of being that will never end. We hope in resurrection not because Jesus was simply resuscitated to continue on in the same manner of life that he had before the cross, but precisely because Christ’s glorification in resurrection-life images our own hoped-for recreation; the same power of God which raised Christ to the newness of life is working within us.
While such thinking is obviously not “reasonable” on the basis of Western epistemological methodologies, its “reasonableness” can, I think, be easily expressed in the symbiotic relationship of belief and lived-life. As we articulate the hope of resurrection as a theological concept (not simply as an “historical” event), people will be able to see the natural place that it assumes within how Christians view life, reality, and the meaning. They will see that our hope is not simply in the historicity of the resuscitation of a dead person, but rather in the consummation of God’s loving, eternal purposes within creation.
As mentioned in my last post about Web SQL databases, each Web SQL database consists of a unique name and version. Each database, however, can only have a single version at any given time, so there’s no possibility of older and newer versions running concurrently. To quote the spec, this is provided to “…allow authors to manage schema changes incrementally and non-destructively, and without running the risk of old code (e.g. in another browser window) trying to write to a database with incorrect assumptions.” In other words, instead of trying to manage the hassle of temporarily offloading data, rebuilding the data structure from scratch, and then reloading data when code changes, versioning allows for the detection of the client’s current db version, with the option of programmatically upgrading them to a different (read “new’) version of the database schema. Of course, you could conceivably also use this to detect old versions and point to different code entirely, but that would be a lot of code to manage…
My idea on this is to use the versioning as a way to push incremental database schema changes in a systematic way. For example, you could easily define a complex series of schema updates that take the user’s database version (whatever it might be) directly to the most current version. However, this seems like an undue amount of work to me. Rather, I think that maintaining a procedural update history of each version makes more sense.
Here’s the idea. Let’s say that we’re building a blog. Perhaps version 1 of our database is very simple: just a “posts” table that captures title, content, publishdate, and author.
VERSION 1
posts
postid
title
content
publishdate
author
But let’s say in version 2, we add two more tables (comments and categories, for example).
VERSION 1 ---> VERSION 2
posts posts
postid postid
title title
content content
publishdate publishdate
author author
comments
commentid
content
author
publishdate
postid
categories
categoryid
category
Now our approach is increasing in complexity, for not only do we need to give new users the full version 2 schema, but we also need to upgrade version 1 users to the new schema without destroying their existing data.
But let’s push this out into the future a bit. Perhaps by version 3, we’ve added a few more tables. Now we have to give new users the version 3 schema and upgrade BOTH version 2 and potential version 1 users to the new schema, taking into the account the discrepencies between version 1 and 2, and between both 1 and 3 and 2 and 3.
VERSION 1 ---> VERSION 3
posts posts
postid postid
title title
content content
publishdate publishdate
author author
comments
commentid
content
author
publishdate
postid
categories
categoryid
category
tags
tagid
tag
bloginfo
title
owner
tagline
VERSION 2 ---> VERSION 3
posts posts
postid postid
title title
content content
publishdate publishdate
author author
comments comments
commentid commentid
content content
author author
publishdate publishdate
postid postid
categories categories
categoryid categoryid
category category
tags
tagid
tag
bloginfo
title
owner
tagline
Oh, and we just realized we need to add an additional column to our original “posts” table, so version 3.1 increases the complexity yet again.
How do we manage this? Do we write a full complement of schema updates to get each version (1, 2, and 3) to the current version (3.1)? If we do, this will be a lot of code. Do we simply write a bunch of clunky “if exists” procedures in our sql to account for gaps in our schemas at any stage in the versioning? It’s a better solution, but is still lacking, IMO, because it doesn’t really show how the changes are occurring across versions. If something goes wrong at some point, it’s not immediately obvious where the discrepancy originated.
So my solution is to manage the version updates through incremental upgrades to the newest version by way of any versions in between. Therefore, if our current version is 3.1, a user with the 1.0 version will be upgraded to 3.1 by first upgrading to 2, then to 3, then to 3.1. While this requires a bit more effort than the “if exists” SQL-based solution, it provides an immediate version history, providing great introspection into how each version is related to the previous, and to the next. Let’s look at how this plays out:
First, I create an array representing the complete version history of the database:
this.apphistory = ['1.00','2.00','3.00','3.10']; this.appversion = '3.10';
Then, upon each opening of the database, I invoke a custom method “setSchema” which checks the current version of the database against the current “official” version of the database, and handles the incremental updates if needed:
setSchema = function() {
// set array for holding our sql statements; sql lite can only process one statement at a time
var sql = new Array();
// get history object-- returns current version and whether version is equal to the "official" or current version
var history = this.getHistory();
// if client db version is not equal to current appversion, start iterative update
var ver = history.iscurrent ? this.appversion : history.current;
if(!history.iscurrent) {
switch(ver) {
case '1.00':
sql[0] = "create table comments(commentid,content,author,publishdate,postid);";
break;
case '2.00':
sql[0] = "create table categories(categoryid,category)";
sql[1] = "create table tags(tagid,tag)";
break;
case '3.00':
sql[0] = "alter table posts add created";
sql[1] = "alter table posts add updated";
break;
// default will be a snapshot of the current version of the schema;
default:
sql[0] = "create table posts(postid integer primary key autoincrement,title,publishdate,author,content,created,updated);";
sql[1] = "create table comments(commentid,content,author,publishdate,postid);";
sql[2] = "create table categories(categoryid,category)";
sql[3] = "create table tags(tagid,tag)";
sql[4] = "create table bloginfo(name,owner,tagline)";
}
this.database.transaction(function (t) {
for(var i=0;i<sql.length;i++) {
t.executeSql(sql[i]);
}
});
this.setVersion();
}
}
What’s basically happening here is that the “default” case will always have what the “official” version of the database should be. In this case, this is the “3.10″ version of the database. So if any new users come to the site, they will get the full-on copy of this database written to their client. If, however, they have a previous version of the database, they don’t need a full upgrade to the 3.1. Rather, they only need incremental changes to get them to the current database version. Therefore, if the client has a “2.00″ database version, they will execute SQL statements to get them to the “3.00″ version, and on the next pass of this method, they will get the final incremental change to “3.10.”
And in the future, when additional tables or columns are added/modified, the “default” case can be updated to include the changes, and a case for “3.10″ can be added to manage the incremental change to the newest version.
As I mentioned before, this is perhaps not the prettiest way to manage this. The thing I like, however, is how explicitly it defines the relationships between the versions. With a quick glance, we can see what changes are occurring from version to version. And, because this is an iterative process, we don’t have to worry about updating the “version 2.00″ case to get the client database directly to the newest version (imagine doing that for 50 versions…yikes!). Rather, because the upgrade from 2.00 to 3.00 will ALWAYS be the same, we only have to worry about keeping the newest and most recent versions synched, as this process will take any previous version iteratively through to the official current version.
A while back, I wrote up a quick post about some of the new client storage options that will be available in HTML5, particularly localStorage and sessionStorage. While they are both pretty nice alternatives to the clunkiness of managing client cookies, they are definitely limited. The biggest limitation is the data structure that each supports (they’re exactly the same, after all, except for lifetime of the data). As I pointed out, while their storage capacity is much greater than that of the old cookie, all data is still managed as key/value pairs. Of course, you can always use JSON encoding to store complex data structures as strings in these options…however, if you need to get at deeper levels of data relationships, these will quickly get VERY clunky and unusable.
Enter Web SQL databases. As the name implies, Web SQL databases are, well, client-based SQL databases (SQL Lite, to be exact) that can be levered through JavaScript. Each “origin” can have a number of databases, each of which has a unique name and version (more about this later). If you use something like the Developer Tools in Chrome, you can see these databases in action–including the databases themselves, child tables, and any data that has been added to the tables.
Working with Web SQL
The doorway to creating and using Web SQL databases is the openDatabase() method. It doesn’t matter if you’re creating a new database, or creating a connection to an existing one: this is the first thing you’ll do, and here’s what it looks like:
this.database = openDatabase('Blog',"",'A Blog to Rule the World',2000000);
The openDatabase() method takes 4 required arguments:
- Name: Any valid string, including the empty string, is acceptable. Database names must be unique, however, and should be evaluated in a case-sensitive manner
- Version: The version of the database to open
- Display Name: A friendly name that the browser can use (in prompts, etc.)
- Estimated Size: Each database has a default maximum size, and users will be prompted to allow this to increase if the data exceeds the default quota. Specifying a particular value here can avoid this annoyance by telling the browser up front what the total size might eventually be, short-circuiting the otherwise annoying prompts at each incremental increase (e.g., at 5, 10, 15, 20MB…)
Additionally, there is an optional 5th argument– callback method. This callback method will be invoked if the database is created (not opened), and per the spec should be used to invoke the changeVersion() method to set the appropriate version of the database. If no callback method is specified, the database will be created with whatever version is specified in the openDatabase() method invocation.
Now that we’ve got an open connection to our database, let’s do some stuff to it!
SQL Transactions
The core of working with your now-open connection is the Web SQL transaction() method. [There's also the "readTransaction()" method, which allows for read-only access]. This method takes 1-3 arguments, including the following:
- SQLTransactionCallback: This is required, and is the executeSql method that will actually execute the sql command (more on this later)
- SQLTransactionCallback: Optional callback method to handle transaction errors. This method passes both the transaction, and an error object which contains, among other things, a message describing the error
- SQLVoidCallback: Optional callback method executed upon a successful transaction
A really cool part about the transaction() method is that it provides the ability for rollback. This is why, in short, the actual execution of the SQL is wrapped in a transaction. It’s kind of a pain if you don’t care about rollbacks, but if you don’t care about rollbacks, maybe you don’t care about data integrity
Here’s what a transaction might look like:
database.transaction(
function(t){
//execute sql here...
}
);
Executing SQL
Now that we’ve created a transaction() method wrapper, we can actually get down to running some SQL. This is accomplished by the aptly named executeSQL() method. This method takes up to 4 arguments:
- SQLStatement: A valid string representation of the SQL to be executed (this, obviously, is required)
- Argument Array: An array of arguments to be matched in SQL statement (more about this later)
- SQLStatementCallback: An optional callback method to be invoked on successful execution of the SQL statement–this method passes the transaction and result set from the query…so it’s pretty important to specify if you want to return data from the database…
- SQLStatementErrorCallback: An optional callback method to be invoked when the executeSql() method fails–this method passes the transaction and error object
So let’s say we want to create a new table called “posts” with a few columns. Our full transaction/executeSql() statement might look like this:
database.transaction(
function(t) {
t.executeSql("create table posts(postid integer primary key autoincrement,title,publishdate,author,content);";
}
)
One thing to note, especially relating to schema creation, is that in SQL Lite, only one SQL statement can be executed per request. So for example, if you’re trying to create multiple tables at one time (like when you’re building the schema for your database), you’ll have to pass the SQL statement for each table creation to an individual executeSql() method. To streamline this, I simply create an array of SQL statements, and then iterate over them in a loop. I’m sure there are other fine ways to accomplish this as well, but this works for me.
Preventing SQL Injection
If you’re a web developer, you should always be aware of the possibility of SQL injection, and do all that you can to prevent it. Because of the way that Web Sql is structured, it’s probably a pretty big temptation to build SQL statements on the fly. DON’T DO IT. This just opens the door to SQL injection, and because this is all happening in JavaScript, it would not be hard to identify where SQL is being dynamically generated and exploit it.
To help prevent SQL injection, the 2nd argument of the executeSQL() method, the Arguments array, allows you to specify “placeholders” in your SQL that can be substituted at execution time with scrubbed and validated data. It works like this:
var sql = "insert into posts (title,content,publishdate,author) values (?,?,?,?,?)"; var val = new Array(t,c,p,a); var executeSql(sql,val);
As you can see, in the actual SQL statement, I used “?” to specify my argument’s placeholders. Then, I created a new array containing my scrubbed values coming from the client. Then, I simply passed both to my executeSql method, and it works brilliantly. Simple. Of course, since I’m passing an array and not a key/value pair object, the order of the arguments compared to the placeholders is EXTREMELY important. Just keep that in mind
Finally…Getting Some Data
So far, we’ve seen how to establish a database connection, create transactions, and then execute SQL against the database. Now let’s talk about what to do with the data once we get it.
If you’ll remember, the executeSql() method provides an optional (although recommended) callback method that returns a results object from the executed SQL. This object contains the following:
- insertedId: This is the id of the row that a SQL execution inserted, if any. If multiple rows were inserted, it returns the id of the last inserted row. Very handy.
- rowsAffected: This is the number of rows affected by the SQL execution.
- rows: An object containing any rows returned from the SQL execution
Once you’ve got the “rows” object to work with, you can retrieve an individual row’s data like so:
var row = results.rows.item(num); var title = row.title; var author = row.author; var content = row.content;
As you can see, each “column” in the row can simply be accessed by its name in the object. Pretty simple, huh?
So What’s the Point?
As we’ve seen, working with Web SQL databases is pretty straightforward. If you’re familiar with anonymous functions, and have a good grasp of general SQL, this is easy stuff. Plus, because it is SQL based, the concepts involved with managing the data and database structure are no big deal, and you can concentrate more on developing the connections, error-handling, etc.
But on a more conceptual level, what’s the point of this? After all, this is still a client-based solution. If the user goes nuclear on their client history settings, any databases will be wiped out. If this data, in that sense, is still so “temporary,” why bother with it?
Obviously, Web SQL databases are not intended to be replacements for server-based solutions. On some level, data does need to be managed in a controlled, secure, and “permanent” way. Web SQL is not going to change that. What it will change, however, is how application development happens.
For example, consider the present situation. If you’re developing an application that needs to regularly (let’s say once a minute) save data states for your users, the way to do this is through either clunky cookies (blah) or regular server-side hits to save records to a managed database. While this works, it’s expensive. Depending on the size of the data and amount of traffic, this could result in thousands and thousands of remote requests hitting every couple seconds. If you have the hardware to handle this, it’s not a big deal. But if you don’t, it can take it’s toll.
So what if you could reduce this by a quarter? Or half? Or a 75%? Imagine this: instead of hitting the server every minute to save a data state, you could instead change the schedule to once every 5 minutes. During those 5 minutes you could still have the same routine running, only in this scenario it would be saving the data state to the client Web SQL database. Then, after 5 minutes, a protocol could transfer the saved datastates from client to server. This will be entirely seemless to the user, and will save load on the server by making the requests less frequent.
Or imagine making your applications available offline. When connected, the client machine could maintain a synchronized set of data with the remote server. Then, when the client goes offline, they could continue working with the application, utilizing the data from their machine’s synched data from the server. Then, when they are available to get online again, the client data repository could be resynched with the remote server, pushing any new or modified data. While the experience between offline and online states would be different in some ways, the very ability to be able to work online and offline in a more or less seamless manner is a radical paradigm shift for web-based applications, and opens up the doors of some very exciting possibilities.
The Demo
Ok, enough of this post. If you’re interested in learning more, be sure to check out the W3C spec of this.
Also, be sure to check out my demo (use Chrome…). It’s a simple blog manager that allows you to create, edit and delete posts. Check it out!!
switch(ver) {
case ’1.00′:
sql[0] = ”create table comments(commentid,content,author,publishdate,postid);”;
break;
case ’2.00′:
sql[0] = ”create table categories(categoryid,category)”;
sql[1] = ”create table tags(tagid,tag)”;
break;
case ’3.00′:
sql[0] = ”alter table posts add created”;
sql[1] = ”alter table posts add updated”;
break;
// default will be a snapshot of the current version of the schema;
default:
sql[0] = ”create table posts(postid integer primary key autoincrement,title,publishdate,author,content,created,updated);”;
sql[1] = ”create table comments(commentid,content,author,publishdate,postid);”;
sql[2] = ”create table categories(categoryid,category)”;
sql[3] = ”create table tags(tagid,tag)”;
sql[4] = ”create table bloginfo(name,owner,tagline)”;
}
this.database.transaction(function (t) {
for(var i=0;i<sql.length;i++) {
t.executeSql(sql[i]);
}
});
this.setVersion();
}
It’s been a few days since my last post. It’s partly because I’ve been busy at work, but also because I’ve been working on a super-sweet demo for a new post, which I hope to publish tomorrow.
While you’re waiting, why not check out the season premier of Psych?
A common requirement in the era of Web 2.0 (and beyond) technologies is the ability to have “smart” client interfaces that are aware of changes that occur on the server (data, sessions, etc.). Most approaches include some manner of AJAX that regularly polls the server for changes. While this is easy enough to accomplish, it can be a taxing and somewhat annoying process. After all, wouldn’t it be much better if the server could communicate to the client when it has something share, rather than the client mindlessly asking over-and-over-again for the same thing?
In HTML5, this becomes a reality. Enter Server-Sent Events. In a nutshell, server-sent events “enable servers to push data to Web pages over HTTP or using dedicated server-push protocols.” This means, basically, that the client doesn’t have to keep asking for information: the server will notify the client when new information is available.
In it’s present state, server-sent events are only available for Opera and Chrome (6) dev releases. Additionally, they are currently implemented in two different ways. For Opera, the technology utilizes a DOM element (), while Chrome is entirely JS based. For this overview, I’ll be concentrating on the Chrome implementation.
For the example I worked up, I’ve created a simple chat interface. The basic idea is that two people share usernames, entering them into their respective client interfaces. When each chat message is sent, the record is saved to a database on the server, and an independent page continues to query the db for new data pertaining to the chat session. If new data exists, it pushes it to the clients’ interfaces.
The Code
So first things first. Let’s create our EventSource, the base object that we’ll utilize to make the magic happen:
serverevent = new EventSource("serversent_helper.cfm");
serverevent.addEventListener('message', onMessageHandler);
This is easy enough to see what’s happening. Basically, I define a new EventSource, and pass to it the server-side page that will manage the pushing of data. Finally, I add a listener to the “onmessage” event of the EventSource, which then in turn calls a user-defined function to do whatever with the data from the server (an event object is passed in the callback method).
That’s it. Seriously, pretty simple. From here, the rest is basically getting the data from the server to be in the proper format to work with the EventSource. And this is where it gets a little murky. Per the spec, the data pushed from the server has to be in a very specific format. To be honest, I spent more time than I’d care to admit on this. But it was a good lesson.
There’s a lot in the spec about this, so I’ll only cover the most important details. This is from serversent_helper.cfm, the source specified in the EventSource invocation:
writeoutput("data:"&serializejson(message)&chr(10));
writeoutput("id:"&qmessages.messageid&chr(10));
What I’m not showing you is the queries I used to create and retrieve data from the chat sessions. Assuming that a chat to be pushed exists, this is the code that generates the data pushed to the client.
First, notice the content declaration of “text/event-stream“. This is incredibly important. If your content is not in this format, the push from the server will not work.
Next, notice the output sections. Per the spec, data pushed should be in the following format: “data: [string]“. It is the combination of “data:” and an accompanying string that makes the push work. Without it, nothing will happen. Following the “data:” declaration, I’ve also set “id:”. This is important because you can optionally tag each push with an id which will then be subsequently passed as a header in future interactions between the client and server. Specifically, the header “Last-Event-ID” will be used, so if a connection is lost, the last-used id can be processed when the connection is restored, picking up where it left off.
Finally, notice the newline characters at the end of each line (“chr(10)” in ColdFusion, “\n” in other languages). This is EXTREMELY important because the “field names” of the response are processed on the basis of the newline characters. In this example, if I did not put the newline character after the “data” block, my response would look like {…jsonstring…}id:numeric, rather than just {…jsonstring…}. Additionally, the Last-Event-ID would not get set.
And yes, you can use JSON, so not problems at all pushing complex data objects
Additional Methods and Considerations
I didn’t use these in my demo, but thought I’d point them out anyway. Besides the “onmessage” event, you can also add listeners to the following exposed events from EventSource:
- onopen – fires when connection between server and client is created
- onerror – fires when there’s an error in the connection
And in addition to the url and Last-Event-ID, the readyState attribute is available from EventSource. As its name implies, readyState represents the current state of the connection, and can take the following values:
- CONNECTING = 0
- OPEN = 1
- CLOSED = 2
Wrapping Up
As mentioned earlier, because of the relative newness of EventSource, its implementation is severely limited. However, I think it is a pretty cool idea and I can think of lots of potential uses for this, specifically in relation to connection-less data pushing. I’m excited to see how this develops as the spec is more well-defined and more browsers begin to implement it.
A note about the demo. It definitely works, but there are a few things to keep in mind:
- It will ONLY work with the latest dev version of Chrome (v. 6). If you try it in any other browser, it will be quite disappointing
- Because it’s just a quick demo, you’ll have to arrange a chat with someone with the same dev version of Chrome, and you’ll have to coordinate the usernames that you’ll use to try it out, given that the chat sessions are based on user-entered names
- Sure, I could have made a static example…but I thought the chat would show off the tech a bit more…so sue me!!!
A few days ago, I shared my *official* thoughts on Final Fantasy XIII.
Not having touched it since then, here are some additional random thoughts, in no particular order or meaningfulness
- Final Battle Blues: The final battle (was it 3 or 4 obligatory boss forms?) was WAYYYYY too easy. It could be that I simply leveled up too much in my aborted attempt to complete all of the beast “marks,” but I took out the final baddie (Orphan) without breaking a sweat. In fact, besides the necessarily non-lethal “Judgement” strike in the next-to-last form, all my character’s HP stayed well above half. Of course, that means that I had much more time for slicing and dicing, making quick work of him. Even the dreaded “doom” that was cast on my party in Orphan’s final form was no big deal whatsoever. I annihilated him so quickly that I didn’t even have to think about trying to get around certain death. Pathetic.
- The End of Big Hair?: A hallmark of FF games is big, spiky, crazy hair. From Cloud’s lethal spikes to Wakka’s cone-dome, big, flashy hair has been a certainty. And yes, although we all realize that such hair is, on the basis of physics, entirely impossible, it’s still awesome. Since X, however, the trend has been toward more realism. So while the hair looks more “natural” in CGI, it’s lost is Final Fantasy-ish-ness. I, for one, acutely feel the loss.
- The Hunt for Experience: In FFXII, the chief means for gathering experience points was to take on missions of hunting down deadly beasts of varying difficulty and temperament. These quests took one all over the Final Fantasy world, sometimes with quite annoying time investment. In Final Fantasy XIII, the experience gathering was radically transformed by the idea of “marks” which involve hunting down deadly beast of varying difficulty and temperament. Oh, wait..uggh. I understand that the series is now 13 installments old…but seriously, how about something original?
- My Kingdom for a Writer: While FFXIII was definitely the best of the series in terms of sound-to-character sync, the writing was, in a word, HORRIBLE. The storyline was *okay,* but the narrative path to the end of the plot was brutal. The biggest violators were the sequences between Snow and his fiance-turned-L’cie, Serah. True enough, there’s something to be said for trying to develop a storyline and accompanying dialogue to conjure an emotional connection between the player and the characters. But these sequences made day-time soaps look like Oscar contenders. Quite brutal.
- Eat This: Given the inevitable grind of experience-gathering random, incessant battles, there is a certain necessity in giving the characters something to “say” in the midst of a battle, and such paradigms have led to some humorous and memorable sound-bytes (Lunar 2, anyone?
). However, some of the in-battle dialogue in FFXIII was less than stellar. While I appreciated Lightning’s sarcasm in “You’ll make it” whenever she healed someone, Fang’s incessant “You’re gonna squirm” was highly annoying.
Despite the hit-and-miss nature of this kind of dialogue, I swear I came across a couple mistakes. The funniest one was when I placed Fang into a healer role. While she was in the midst of a Commando attack, I suddenly switched the paradigm so that she turned and healed Lightning. However, the sound-byte from her Commando role was still on her lips, so as she turned and healed Lightning, she shrilly screamed “Eat this!”. It was awesome. - That’s What She Said: From Hope, when seeing the giant Titan monster on Gran Pulse: “That thing’s so big, I can’t tell how far away it is!”….

