Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2001-604
$eventId
ID of event: wwdc2001
$eventContentId
ID of session without event part: 604
$eventShortId
Shortened ID of event: wwdc01
$year
Year of session: 2001
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC01 • Session 604

Introduction to Enterprise Objects Framework (EOF)

WebObjects • 1:05:37

This session presents an introduction of the Enterprise Objects Framework (EOF) with both a conceptual overview to get up and running with EOF as well as practical code examples. This session should prove useful to beginners and experienced EOF developers alike.

Speaker: James Dempsey

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good afternoon. My name is James Dempsey and it is now 5:00 on day two of that annual drink from the Apple fire hose known as the Worldwide Developers Conference. So is everybody's brain full yet? good. We'll try to fix that this afternoon! So it's been very nice the past couple of days, seeing former students who've gone through our Apple iServices classes, folks that I've been teaching web objects to for the past couple of years, hearing about the stuff that they've been doing with web objects, and it's been a lot of fun. So again, other former students who haven't said hi after the class -- or after the class -- after the session, feel free to say hey.

All right, so today we're going to talk about the Enterprise Objects Framework. Before we begin, though, I need to take a couple of polls, and I want you to respond with loudest, thunderous applause you can if the question applies to you. So first, how many folks were here yesterday for Steve Heyman's introduction to the Web Objects Technology Session? So And it's very obvious that it was a session that you're all very disappointed in from your response. That, I just cannot wait until that is out on DVD because I think it's going to just bump Austin Powers off of the list for me.

If not that, it's going to do it to Dude, Where's My Car? So I'm not sure which. So we're here to talk about web objects. The second thing I wanted to pull you on is how many of you consider yourself either brand new or relatively uncertain or a novice in the Enterprise Objects Framework? Again, with a round of applause.

which is a good size of the audience, which is very good because that's what we're going to be talking about. Now let's begin. The introduction, this is an introduction to the Enterprise Objects Framework which is more succinctly known as EOF. And what we're going to be talking about today in Steve Hammond's preso yesterday, we saw that WebObjects and EOF can be a lot of fun. He was wiring stuff up, they got maps flying all over the place. And the question you may ask yourself is, is all this stuff really that easy? And the answer is actually yes and no.

So, yes it is, if you are doing traditional database stuff, inserting stuff, fetching stuff out, creating new objects, the answer is no if you start having to do very complicated things. Like you come into a situation where they have a legacy database that's been there for the past 10 years and they're encoding all this information in the primary key.

And so you have to generate primary keys with EOF and then other situations where they need you to interact with some system that was designed before people had any common sense. And so you have to do all these contorted things to get things to work. And in those cases, you know what? Without even EOF in the picture, it's just hard.

Now, the nice thing about EOF is that it allows you to solve those almost impossible problems Is it easy? No. But are they incredibly hard problems? Yes. And does EOF let you do it with, with, with grace, style, panache, and without writing too much code? Definitely. So that's what we're going to talk about.

Now what are we going to learn in this session? The first thing we're going to learn about is why EOF? Anyway, what's the purpose? What do I get? Why am I in this session? What's going on here? The second thing we're going to talk about is just a conceptual model about EOF and how it works because we've seen things flying out of databases on the web pages today and yesterday and for the rest of the week. But I always get a little suspicious when it seems a little too magic-y. So we're going to demystify a little bit of just what's going on there. We're not going to go into excruciating detail.

Finally, we're going to do practical code for basic database operations. Now, yesterday, Steve Heyman, a proud Canadian, He said that Canadians, they don't need wizards. They don't need assistants. He was going to use a display group to fetch things. It's a little known fact, but a true fact that I am half Canadian. My father immigrated to this country during the great Molson Beer famine of 1958. And he took the arduous journey, 20 minute journey in his car to Maine and never returned. Except to visit family and friends. Mainly because he liked the idea of Molson being imported.

So that said, I have the Canadian blood of my father racing through my veins, yet I'm also a rugged individualist American who doesn't need a display group. And so therefore, what we're going to do in this is we're going to see the programmatic code that actually a display group is using behind the scenes and expose another level of the magic of EOF. So that's what we're doing.

Now where does this all fit into the big picture? EOF is actually a slight misnomer in that there are a number of frameworks in EOF. The two that we're focusing on are EO Access and EO Control. And these are frameworks that they form the core of database access if you're doing HTML based WebObjects apps, Cocoa apps, Java client apps, direct to Java client apps, direct to Web apps. Anything that you see in any of these sessions that is hitting a database is using the frameworks we're going to talk about.

Alright, that said, if you are a very good piano player, imagine you have never played the piano before in your life. And for those of you who are either not very good piano players like myself, or never seen a piano before, Imagine being walked up to a piano and handed a piece of music that looks like this.

You'd probably say, "Uh, okay." It looks very complicated, it looks very daunting, it looks like how am I ever going to sit down and do this? But we know from experience, we know that there are people in the world who can sit down at a piano and play this very piece of music. We know walking up to a piano that it's in there somewhere, I just don't know how to get it out. It's just like EOF.

Because we know from the many years that EOF has been in production in the largest companies around the world, we know that EOF is able to solve some problems that would make your head literally explode. Oh, I've heard stories. But, just like you don't want to hand this piece of sheet music to somebody the very first time they sit down at a piano, you don't want to do this, those extraordinary complicated things, the very first time you deal with EOF. We know anybody who's gone down the little trail of learning to play the piano knows that you start here.

Okay, and you say, "Oh, how disappointing." But we know that when you're starting to play the piano, somebody tells you, "Take this thumb, put it on this key called middle C, and then just kind of walk up the scale." Those are the fundamentals, and you practice that. You do that over and over again because those are the things you do all the time when you're playing the piano. Similarly, we're going to talk today about those things that you do all the time when you're working with EOF. And get started by playing with those things rather than trying to sit down at the piano for the first time and muddle through that.

That's easy. I could do that. Okay, enough with that. Now let's move on and let's talk about why EOF. What's the whole point here anyway? So, from, we can look at EOF kind of from two points of view. One point being from the point of view of I'm an object oriented programmer or individual who thinks that way.

And then the point of view of I'm a database kind of person and I'm not really sure about all this OO stuff. So let's start talking from the object perspective. Just a brief review. We have different types of things called classes. Each of those classes stores different pieces of information, instance variables, state, however we want to put it.

In addition, each one holds on to certain amounts of logic. Okay, canonical description of an object. But the big question being, where do objects sleep at night? What happens when I need to, if it's a desktop application, Cocoa application, I need to, the user logs out or shuts down the computer.

What happens if I need to recycle an app on my server? What happens if the power goes out in California? And suddenly I've lost all the state in my object. So I need somewhere to put that. And I could put it in a flat file, right? Serialize it out, archive it, have it all written out as some big text file.

But once you get over a certain number of objects, that gets to be ridiculous. So you need some place to stick the data. And boy, a database seems like a pretty good idea. That's what they made them for. And so it actually turns out that in sticking information or object related information into a database, it actually turns out to be a pretty good match.

Of course, we have types of things in our object model, maps to tables in the database. You've heard this probably at least seven times in each session so far because actually this mapping is the key to EOF. This is the first fundamental thing that you need to be thinking about. And also, of course, we have columns in the database that hold different types of information and it maps so well to instance variables. And then each row in the database maps amazingly well to an instance of an object of a particular class.

So that's good for everything except for types that are more complex than a string or a number or a date. How do I hook up things that are complex objects? And we know that in Java we have an object that is referencing another complicated object. It's not a pointer, mind you. Although we can get null pointer exceptions, which boggles my mind. I don't understand that at all. It's just a point to a unique place in memory, a reference if you will, but not a pointer. Wouldn't do to have that.

In fact, in the database it actually works out almost identically how it works. Each row has a unique primary key. And then in another table, a row has a place to store the value of the unique primary key called a join. In the world of entity relationship modeling, from mapping that object to relational model, we call this a relationship.

So the point of EOF is to go from a row to an object and back. How hard could that be? Now, what is an Enterprise Object anyway? We hear this term bandied about all the time. Well, We affectionately call them EOs or just because we don't want to say Enterprise Object all the time. All that it really is is it's an object that implements a certain interface, the EO Enterprise Object Interface strangely enough.

Although you would not want to go and implement that interface yourself. That would be akin to you getting up tomorrow morning and saying, "You know, I think I'm going to invent this round thing today that people can use to roll on." Or something like that. Maybe I'll call it a wheel. Yeah, that would be a good idea. Don't reimplement the wheel. You subclass EO Generic Record.

So it's all done for you. All that that does, essentially, is it allows these objects to work with the Enterprise Object Framework and persist in the database. Now, why do I bring this up? Because if you're looking through the documentation or the class browser, you will see a lot of the methods.

Take arguments or return values of type EO Enterprise Object. So, what's the difference? So that's from the object perspective. From the database perspective, having taught folks over the years, I can tell you that EOF can freak a DBA out completely. They go, because as was mentioned in previous sessions, they, you don't have to write any SQL. When you get the objects into your application, there's no primary key, there's no foreign key. It's kind of like your entire world is a DBA. You've been abstracted from it, and it, that would freak me out too.

So, as you start working seriously on WebObjects applications and you are working with DBAs, don't get cheesed off at them because they are coming from a different place. And be very patient with them because this is kind of like... Actually, it's a lot like getting dropped in the middle of a foreign country where you don't speak the language and things are completely different and everything you're used to is not quite there anymore. And even worse yet, it's all kind of right there and you could get to it if you wanted to, but you're not supposed to.

So you stick data in a database. You can also put logic in a database. Most database vendors have devised some procedural language you can store in the database called a stored procedure. Let's talk about EOF and how it can add value or what it does in relationship to a database. So one is distributed processing.

If I have a big website, a big -- I don't want to put all my logic in my one database because in addition to fetching and saving changes back to the database, it's processing all this stuff so I can offload the processing to one or multiple WebObjects applications. Second thing I can do is write my logic in standard Java. I don't have to learn Oracle's brand of some procedural thing.

Dynamically generated SQL, as has been kind of testified to by a couple of folks up here, they didn't know SQL all that well. And to tell you the truth, I could not write a well-formed SQL statement right now if you paid me a large sum of money. I'd have to check some documentation. Why? Because using WebObjects in EOF for the past few years, I haven't needed to. And it's always done the job for me.

One very, very nice thing in EOF is the ability to connect to multiple data sources. From the point of view of your code, you don't even necessarily care where those objects came from, where those rows came from. You're very nicely abstracted from the idea of multiple data sources.

Finally, you get a separate scratch pad for every user. So if you can imagine an application where a lot of people are fetching information or looking at information and they want to maybe try a change. Okay, I'm going to update this number and see how it affects related numbers.

Well, if you just have a database, the only place you can store that change is in the database and then you have people writing and overwriting over each other, which is a bad thing. So in EOF, you have a place where each user can make edits without affecting anybody else. It's like a little alternate universe where you fetch in information and you can literally make changes to that information, a little context to do editing, if you will.

How'd that name pop into my head? That is another very useful thing about EOF. In fact, so useful, let's talk about that editing context for a while. The EO Editing Context class is the class. It's like your go-to guy. If you want to do anything related to all the basics of database access, you're going to be talking to the editing context.

If you want to fetch from the database, you make up an object that specifies what you want and you hand it to the editing context, you say, "Go get it." If you want to Insert objects. You make a new one, you hand it to the editing context, you say, here, I want to stick this into the database the next time we save our changes back.

If you want to, well, I've been watching The Sopranos a lot, if you want to whack an object, you're going to take an object that you've already fetched in and you tell the editing context, hey, I don't want, I want this thing gone. I want to delete it.

And it also, when you're changing objects, you don't even have to do anything. The editing context is just watching. Just sitting there saying, okay, you made a change. I gotcha. It's a very nice thing. And then at the end of the day, when you've done all your edits, you have the choice either to chuck them, revert the editing context, or save all of those changes in one big transaction down to the database.

Editing context, very important. Now, we're going to see some code. We're going to walk through each of these and I'll show you how to programmatically do all of these items. Now I brought up the display group earlier, the WoW display group, which is an object that sits on top of an editing context. And all of the magic that you've seen, right, with dragging things up, things are being fetched automatically, they're all happening. They've all been happening because a display group has been talking to the real power behind the scenes, the editing context.

And so all of the methods that you see here are essentially what the display group magically has been sending the editing context. There really is, when you start to look at it, not really so much magic, it just really looks that way because the whole system is put together so well. So let's get into it.

So fetching. When you start doing some fetching in WebObjects, you will find that there are many techniques for fetching. We've seen a couple already. One is using a display group to fetch. In the prior presentation, there was a method from EO Utilities, a convenience method for fetching. We're going to see two ways to fetch in this presentation. No matter which technique we use, there's still a canonical thing that always happens, and that's what we're going to go through, the canonical longhand way. It's kind of like I'm going to teach you long division, and then after that, I'm going to give you a calculator.

So, first you create a FET spec. A FET specification, we'll see in a moment, just specifies what I want from the database. I have to get hold of an editing context conveniently enough in a WebObjects application. Every user has a session and every session has access to or can lazily create a default editing context.

So it's very easy to get hold of one. And then I tell the editing context, "Hey, here's a FET specification. Go get me the objects that match this." The editing context does the work of talking to its friends at the lower levels in the Enterprise Objects Framework and you get back EOs. And what you get back is an array of retrieved Enterprise Objects.

And you have a choice. You can either, then you have this array and you can manage that array yourself so if you're adding new objects to the editing context you might also want to stick them in that array. If you're deleting objects from the editing context you might want to remove them from the array so that when you display that array everything looks copacetic. That is something actually that a display group handles for you.

All right. So let's do a fetch specification. What are we going to get from the database? Well, the first thing we need to tell it is what kind of thing are we getting from the database? The entity name. It's just a string. It's the name of the entity in the model. What table are we fetching against, basically? The next thing is something called a qualifier, which is just a description. It's basically an OO description of the criteria of what we're looking for.

And then finally, an array of sort orderings. And sort orderings always travel in a pack. They, you never find a lone one. They're always together in an array. And they determine what we're going to sort on. If you are a DBA, that's wonderful, because I don't know any SQL and you optimize my database and that's great. This is very analogous to the where clause in a SQL statement and the order by clause, the qualifier and the sort orderings.

So a qualifier is basically an object-oriented way of describing a bunch of criteria. So the phrase, I'm looking for employees whose salary is greater than 5,000, and their last name begins with a J. Well, EO qualifier is a super class, and it has all of these subclasses. Some of them are for concatenating things together, like an and qualifier. We also have or and not. All the good ones.

EO key value qualifier is where we put things like salary is greater than 5,000. And then we put in a number, which is 5,000. Now, it would be a real pain in the butt if I had to go and build all these objects and hook them up myself.

So even in the longhand canonical way, there's a slightly easier way to do that. It's a method called qualifier with qualifier format. And essentially what it takes, it's a lot like a printf string in C, where you give it a string with a couple of placeholders or formatting characters, percentage at sign, and the second argument is an array of arguments that are gonna get plugged in to the blanks.

It's like a programmatic madlib. And so essentially what happens in this code example is we make an array, we make an object, integer 5,000, add an object that's a string, and then we call that method and create a new qualifier. And what this code is going to create is this object graph.

[Transcript missing]

So how do we make them? Well, we make an array, usually a mutable one so we can add stuff to it. And then we make new EO sort orderings. The name of the property or key that we're sorting on. And then there are static variables in EO sort ordering class that define the ways we can sort. Compare ascending, compare descending. And then we have case insensitive versions of those for when we're doing string compares.

Then we build the fetch spec. We assume in this case that we already have an array of orderings. We already have the qualifier. We use a three argument constructor to create a fetch spec and give it the pieces of info it needs: the entity name, the qualifier of what we want, and the array of sort orderings. If you want to get everything back from the table in an unsorted way, you could build a spetch fetchification. A fetch specification that takes null for the last two arguments.

And then finally doing the fetch, we get a hold of some editing context and again the session has one that we use as the default. Just any old editing context just happens to be stored in the session. We can ask the session for its default editing context. And we send the long but descriptive method, objects with fetch specification. We hand it the specification, we get back an array of objects. The hard part is not fetching. The hard part is building the specification of what you want. Actually that's sometimes true in software development as well.

Think about that when you go home. Okay, there's an easier way. The graphical Fetch Spec Builder that's part of EO Modeler. This I think is, when I saw this I just leapt for joy. It was a very happy day because I didn't have to write all of this code to build a Fetch specification. Everything that I did in code I could now do in the model. And so I can graphically create and we will see a demo of that in a little bit.

We can create the qualifier this way including building complex ANDs and ORs and NOTs. And we can also build sort orderings this way so that we can not have to make that array ourselves. We can just do it in a tool. Very nice. Now, when you build a qualifier, however, usually you don't want to always get people whose salary is greater than five thousand whose first name starts with J. You usually want the user to type in some input so you can do a fetch. Otherwise it's a really boring app.

So, in this graphical fetch spec builder, there's something a little sneaky. Actually it's very cool. Called qualifier bindings. I can, instead of typing out a literal thing that I'm qualifying against, I can put in that graphical fetch spec something that reads something like last name like dollar sign last name. And that dollar sign last name is a variable that's going to get replaced at run time with whatever the user typed in.

Now I take that ingredient, which again is kind of like a fetch spec with some blanks in it. And how am I going to fill those items in? Well, you kind of got the answer already because it's on the slide. An NSDictionary that holds keys and values. The key in the dictionary that matches that dollar sign variable. I stick those two together and whatever the value is gets substituted in and voila. voila, I have my fully formed qualifier.

which is very very nifty. Now how do I do all this tomfoolery? Well, I can use a graphical fetch spec using an EO utility in one line of code. I heartily recommend this as one of the best ways to fetch programmatically. So, we have an editing context we've already gotten a hold of, probably from this session. We have this dictionary of values, just calling it a query dictionary. And this method, objects with fetch specification and bindings, that's a static method of the EO utilities class.

We handed the editing context we're going to use, the name of the entity we're fetching, the name of the fetch spec in the model, and then finally the dictionary of stuff that's going to get filled into the blanks. It's going to build the qualifier for you, fill in the blanks, build the fetch spec, tell the editing context, "Go get me those objects with that fetch specification." Get back the array and hand it back to the EO. Creating and inserting.

It's actually very, very simple to do. It's a two-step process that a utility lets you do in one step. You need to create an object and insert an object, as this slide kind of gives away. You make a new object, and you can make as many enterprise objects as you want, and they will never end up in the database unless you insert them into an editing context and save the changes.

What this looks like is, what Line of Code does, create an insert instance, is you hand it an editing context, the name of the entity you want to make a new one of, and it will... Make a new one, stick it in the editing context, ready to be saved. And then you will also get back a reference to that new object so you can do what other wonderful things you'd like to do with it.

Editing is the easiest. One of the wonderful things about EOF is that you get to use your objects like objects. If I want to set and retrieve values, I can use accessor methods. And as I'm using those accessor methods, they are automatically being watched, those changes, by the editing context. So that the next time I save changes, the most recent data gets put back into the database.

I also bring up key value coding. This has come up, I think, in every session as part of the fundamental magic of web objects in EOF. I would say, just as a pointer, because we are not going to get into it here, that understanding Key-value coding and dictionaries, especially NS-mutable dictionaries where you can add and remove things, are probably two very key things to the zen of EOF and WebObjects. So, further research for you all.

The idea though is basically in key-value coding it's just an interface that declares instead of always having to write two accessor methods for every property, set name, get name, set salary, get salary. You know, you have 37 properties, you end up with, what's that, six, 74, 74 accessor methods. Let's have two. And we just pass in the name of the property we're trying to get and set as a parameter rather than hard coding it as a method name.

That is what key-value coding is, which also means that as I'm using objects that implement key-value coding and all the good ones do, um, I'm able to treat them and get and set values in them in a very generic way which is really very much at the core of why we can do all the cool, fun, drag-and-drop, easy stuff that we saw yesterday.

And then finally, deleting. If you want to get rid of an EO, it's very simple. You call on your friend the editing context and you say, "Delete this object." And it'll put it on the hit list. That thing is going to be gone the next time you save changes.

So we've seen what? For fetching, inserting, updating, and deleting, we've seen about, what, five lines of code. Very difficult stuff. Now all of those changes are just hanging out in that little scratch pad in that editing context. They're not in the database, they're not bothering anybody else. And in fact, to start from the bottom of the slide, if that user say hit a cancel button on your web page, you could in that action method tell the editing context to revert. Revert, throw out all those changes. All those things you inserted and changed and were ready to delete, just chuck that all. We're reverting. Um, or...

[Transcript missing]

Alright, that is the fundamental way that we deal with EOF using an editing context.

Now I'd like to bring out Mark Respass or up Mark Respass, demogod extraordinaire who is going to be walking us through a sample app that does all of these things. Mark. Mark Respass: Thank you. Oh, I'll do this one. Mark Respass: Am I on? Yeah. Everyone hear me alright? It's really bright up here. Okay, um... What we're going to do is start with the browser.

I've written a small application, so I'm going to start in the opposite way that I usually do demos and show the application first. So, as you've heard so much about CRUD, that's what this application does. We have a small database of songs. It allows me to search on these songs. I can add songs, I can inspect the song, and I can delete it.

So we've got a couple of fields here, song name and price. Of course, if I leave those blank, as James said, when you want to fetch all of your objects, you pass null for the qualifier and null for the sort orderings, and you just get back all the objects. I can of course do searches for a particular song and this one is set up to do greater than or equal to a price. So pretty simple stuff. I can add a song here.

I've got a few pop-up buttons with some preset categories. Maybe we can take rock and Charles Mingus. I can see Mingus doing some rock and dirt, a little collaboration with Alice in Chains. Come back in our research and now we've got that same song. I can hit the delete button because it turns out Mingus doesn't want to do that.

And I can inspect any song and make a change to it. So you can see I actually have an mp3 of this file on my home computer but since this isn't my computer, let's delete it so that doesn't work. And we can go back, take a look at it.

Of course, I can hit cancel and that reverts the changes. So if I were to make a lot of changes and clear out all these fields, hit cancel. That simply invokes revert on the editing context. So how do I do that? How do we do that? Starting with search.

big font. Starting with the search method, as James described, there's lots of ways that you can do this. You can write all of the code. You can create your fetch specification through by creating your and qualifier. In this case, we've got two fields. I'd have to create two EOK value qualifiers, take an array of those, and pass them to an and qualifier, and make that. Create my sort orderings, create my fetch specification, pass all that to the editing context, and ask it to return all the objects.

Or I can just use the, you know. The big font. Hold on. I can just ask it to the ER utilities method to do the fetch for me. Objects with fetch specification and bindings, given an editing context, the name of an entity, the name of my fetch spec, and the query dictionary.

So I'm going to talk a bit about the graphical fetch specs in EOModeler. Because as James was going through all that, you can see it can get pretty complicated creating all of these EO key value qualifiers for every field that you had. You potentially would have a whole bunch of fields in a more complicated application. You'd have to create all these key value qualifiers.

So EOModeler makes it really easy to create these graphically. And you can see here I've got song name, case insensitive like song name, and cost greater than or equal to cost. What I'm going to do is add a couple of fields in here to do more searches. So I'd like to be able to search by artist. Oh wait, let me double check.

Yeah, by artist. I've conveniently written some code in here already. So I add an and qualifier and I'm going to click on to artist equals

[Transcript missing]

toCategory equals Category. What's going to be interesting about this is that for the artist, I'm just binding the toArtist relationship. If you remember, in the custom EO, you can see that toArtist is a method on song that returns an artist object or an EO Enterprise object referring to the artist table.

But I'm only asking it for this particular object here in the fetch spec. For Category, I'm looking at the actual Category field in the Category field. category table, so I can put a string in there. In my WebObjects template, I've got this query dictionary and I've got it bound up to song name and cost, two fields in my song table. I'm going to add a row for the category.

I'm putting in a field and I'm going to bind up my query dictionary using the "Variables I specified in my fetch spec. So query dictionary, dictionary, and then I'm going to add a row below that." for the artist because i conveniently already put in a couple of variables I've got this artist display group.

You may remember in previous sessions where they discussed the display group. You can configure it for a particular table or a particular entity. And this one is for the artist table. I've got it set to fetch on load, sorted by artist name. So it's going to fetch all of the artists. I'm going to bind the displayed objects to the list. I've got an artist object in here for the item.

I'd like to display the artist.artistName And then I've got a selection. In the selection, I'm going to bind query dictionary.artist. Because what's interesting about this is that the pop-up button doesn't give you back a string which is the name of the artist. It gives you back an actual artist object.

I happen to be displaying in the display string the artist name, but the object, the thing I'm getting back is an artist object. So I can pass that particular artist into my fetch spec and say, for the relationship to the artist, find all the songs that match that relationship.

If I go back in here and recompile to get the changes for my model, I'll get these two new fields in here, they'll let me search. I don't have to write any more code in order to get these and out of the thousand demos that I've done, I always seem to forget one binding in this pop-up button, which is the no selection string.

fetch again and refreshing this page now I can select so I can select setting that to none I get all artists I get all the songs by Alice in Chains all the songs that begin with see in this case nothing nothing is found so it's really easy to add this up and add these things into your fetch specification using EO modeler you don't have to write any new code it's all getting set up with my query dictionary let's take a look in a little more detail at how this is getting done I have a query dictionary which is an NF mutable dictionary which I initialize in the constructor And I bound up these keys: query dictionary dot cost, which is a field in my song table, and this one, the selection is query dictionary dot artist, and those all match what's in the fetch specification in EOModeler.

So, and during the request response loop, when WebAuth just goes through this page, it's going to go into each one of those forms and say, I've got query dictionary song name, so it's going to look, set the song name key, and take the value out of that field and put it in.

And remember, in an intramutable dictionary, for anyone who doesn't know, the method is set object for key, so it'll set that, the value, to song name for the key song name, but if song name doesn't exist, it will create a key song name and set that value in there.

And in fact, if these are null, if I were to leave one out, it will actually remove it as part of key value coding, which is how I'm able to do a fetch. I can say, put in two here and find all of these. L greater than or equal to.

I don't know what match is found. If we can make a change to that and I don't keep all the fields that were in my query dictionary. So I also have debugging on on this application. Oh, and if we look at the query dictionary here, you can see that this is actually an artist that was selected, and you get an artist object.

And I have debugging on where you can see that the SQL being generated is the artist ID. And EOF is able to say, find me the artist that matches. Get its primary key out. Match that up with the foreign key that's in the song table. And do the query that way. So the SQL is being generated for me, but I don't have to deal with it. I can just deal with the objects.

So that was the search method. A couple of other things. I can add a song. So we went through and I hit the add song button. It brings up this other page. What happens with that? If I want to add a song, I use the method that James mentioned, create and insert instance, pass it the editing context that I'm using, the session's default editing context in this case, and the name of the entity I want to get an object back, which is a song entity. I have a method here, edit page with song, because I'm actually using the same component to edit new objects and edit existing objects.

So I have edit page with song, which simply sets the song to the song that I return and sets the return page to this, which is why when I come back after creating a song, my page looks the same. Passing this to the next page, I can return that woe component and I get the page back in the same state it was in, which for this demo worked out well for me.

If I were to edit a song, I simply pass it the song that I have. And this is part of some of the magic of WoW repetition. The WoW repetition allows me to select one of the songs in that array, in the table, and it will set the song variable automatically to the one that I selected. I don't have to go through and figure out what it is. The song variable gets set to the one I selected. If I delete, The same sort of thing happens. It automatically sets the song instance variable to the object that I selected in the row.

And then I, as James was talking about, if you were to manage this array yourself, I remove the object from the array, ask the editing context to delete the song, which just marks it for deletion, and then when changes are saved, the editing context saves the changes, deletes those objects.

Taking a look at the edit page, The save song method on here is again very simple. I ask the editing context to save changes and I return the page that I set. Now, you might wonder where are these changes coming from, where is it getting all these values? I can take a song object, you can see all the instance variables here, and I can bind them directly to fields on the form.

I can also bind them to the selection for pop-up buttons, so for each one of these pop-ups I have the object that was selected in the pop-up set to the, for the song binding. So I've got song to album and I can bind these up directly. Hitting Save saves the changes. Hitting Cancel invokes revert on the editing context.

So I just want to try a couple more. Oh, I forgot about the clock. We have plenty of time. All right. So there's more things that we can do. I didn't specify any sort orderings yet. So I can specify sort orderings that maybe I'd like to sort these by artist name.

And we can specify ascending or descending, case insensitive or case sensitive. I believe that this is pretty much if you have Alice in Chains with a capital A or a lowercase a, they show up in two different places. We'd like them to all be grouped together. So, case insensitive, sort ascending, you can sort by song name.

and last maybe do the category. And there are a number of other things that you can do in here. You can set prefetching, which you might find out about in some of the advanced sessions you can do raw fetches and actually get back raw rows rather than getting back Enterprise Objects you just get back a dictionary of raw Rows.

You can set options like fetch distinct rows, I think it's the only SQL I know. Select distinct, well, you know, that sort of thing. We select distinct. If all of this worked out into some SQL that could be figured out, then SQL would be set here. So we can see already that SQL is being generated, but EOModeler isn't really able to figure out, "I've got an artist object.

How does that relate to SQL?" That's part of what EOF is doing for us. So now we've got some sort orderings, we've got qualifiers, we're working across relationships because EOs know about relationships. Lots of database access frameworks don't somehow, they forgot about relationships, the relational part of the relational database.

But with an EO, if I have a song, a song knows about its album, it knows about its artist, it knows about its category, but it only knows about it when we need to get it. When we ask for the artist, that's when it goes and gets it. So now that we've got some sort orderings in there, I'll recompile, get my model back into my application.

I'll bring my application back and now when I fetch, all these should be sorted. There we go. So if we just sort by, fetch all the objects in here, now they're sorted by artist, song name, and category. So we've got all these different songs, Dave Holland, something James Dempsey, I don't know what the Fetch Spec song is. And that's, I think that's pretty much it. We've got sort orderings, we can use EOF to do all this, our EO modeler to create our Fetch Spec graphically. James? Thank you very much, Mark. Let's give him a round of applause. And if we switch back two slides.

Awesome. So the first time I wrote a WebObjects app, it was a little, small app to exercise EOF, actually very similar to this with one addition. It was something that kept track of how many times Mac OS Rumors was right. And so I wrote a little code that went out and grabbed the HTML from their site, parsed through their tags, pulled out the heading of each story and the story itself, stuck it in a database using EOF.

And I went through and picked a date of when I would check back to see if that rumor was true or not. And every morning, because I don't know, just kind of an Apple watcher, I guess I would go in and check that out and 20% is about the ratio.

But that was usually on things that were going to happen tomorrow or the next day, you know. But I highly recommend starting out with EOF writing a small app of this nature that exercises those basic functions. Write one or two. The practice is good. Keep it very simple. It's actually one of the best ways to learn.

The magic still, this EO editing context, it does all this stuff. I just get back this array of objects. Somehow there's SQL being generated. Who's doing what? What's going on here? Well, we're going to take kind of the nickel tour of the EOF stack, of the EO access framework and the EO control framework to show how we go from a row to an EO and back.

Now we'll start with EO Access and EO Access is something where you don't, for starters at least, do things programmatically. You configure EO Access using EO Modeler. EO Access, actually I'm going to jump back a slide. Oh, maybe. There we go. EO Access is responsible for the connection to the database. It's responsible for turning those raw rows into enterprise objects. It's responsible for doing that object relational mapping and it does so with the help or the assistance of a model file.

We don't really mess around in EO Access that much except that the EO Utilities class, with all those utility methods, is part of the EO Access Framework. So when you're looking in EO Control, the documentation, and can't for the life of you find out where this EO Utilities is, it's because it's in EO Access. EO Control, as we've seen, is where we control things. We have an editing context. We fetch, insert, update, delete. That's where we are in control. That's what EO Control is for.

So again, we don't programmatically touch EO access that much. We've seen what EOModeler does, has the connection information of what database we're hooking up to, and has that object-to-relational mapping. Without a model file, EOF is just going to sit there. It's not going to connect to a darn thing.

So the EO Access Framework has actually two layers that we're going to talk about. One is called the adapter layer. And the adapter layer, currently the JDBC adapter, is going to, is the part of the framework that is sending SQL to the database, it's generating the SQL, particular to that database.

It is also maintaining the connection through the database. It is dealing entirely in raw row data. It has never heard of an enterprise object. It's dealing entirely in just the rows that come back. When it gets them back, it hands them up to the database layer. And the database layer has two very important jobs, kind of two raisons d'être. As one would say if one had a very poor French accent.

The two things that the database layer does is first of all its job is to turn that raw row into an EO. It's kind of like Pinocchio becoming a real boy. It was just a plain behaviorless bunch of data. Now it's an enterprise object that represents the logic of your business.

The second thing that it does is it takes a snapshot of the data that came in from the database and stores it. And it holds onto it, one, so we can cache and so EOF might save itself a trip to the database later because it already has the information. We already went to the database.

And it also holds onto it so that when we save those changes we're able to check, "Hey, did somebody change that row out from under us? What were the values when we first fetched those items?" Those are called snapshots and as you go more and more into EOF you'll learn more and more about them. I just wanted to point them out. And let you know where they lived.

So once things are out of the access framework, they're fully formed EOs, the snapshot's been taken, and we move on to EO control. Oh, one more thing. I mentioned earlier that multiple data sources was something that EOF did very, very well. And in fact it's so arduous to set up a second data source.

What you do is you make a second model file. You add that model file to your project. And as you are fetching using entities in both models, EOF will automatically come up with the objects to connect to both databases. And both of those are going to be fetching raw rows, turning them into EOs, and the like.

A note, not all databases are orange. I should have picked a different color to distinguish. It's also important to note, I did not get a chance to change this, that really that whole row, that whole line is the database lake. What EOF is doing is making a couple of objects in each layer for each connection down to a data source. But again, the takeaway, add another model that connects to another data source, you're connecting to multiple data sources. The rest is handled pretty automatically by EOF.

Now, you may come across this object class called the EO Model Group. It lives, it exists because we can have multiple models and so we have an object that manages those models. That's what its job is. Those are kind of the big ticket items of what's going on in EO Access.

Now let's go through. So we've gotten these things up out of the database. We have multiple data sources we might be connecting to. And how are we going to control what SQL gets sent here, what SQL gets sent there, customers live over here, something else lives over here? Well, we have kind of a traffic cop in the EO control framework called the Object Store Coordinator. You'll run across this as you're reading the documentation. You don't talk to the Object Store Coordinator programmatically all that often. It's just nice to know that the OSC is there just directing traffic for you.

And then on top of the Object Star Coordinator is the thing we're familiar with, the editing context. So I wanted to just show you how things get from the database and who are the players along the way so that you don't think it's just magic and I don't understand exactly what's going on. This is pretty much the grand tour of EOF.

And of course we can have different editing contexts by default one per user session. And they're all talking through the same object store coordinator. They're all using that same model. They're all sharing the snapshots stored at the database layer. And they're all connecting through the adapter layer. So that is the big ol' walkthrough of EOF. Now, um, Let's review. So, well actually, I wrote a little song about it, so.

[Transcript missing]

So how many object persistence frameworks in the world are there that people enjoy using so much that they write a little song about them?

[Transcript missing]

EOF is a software-based software that allows you to specify the objects you want to fetch as its name implies. With a fetch spec you can stipulate those objects you want to fetch and manipulate.

[Transcript missing]

♪ Fitch, spec, baby you can stimulate those objects ♪ ♪ You want to fetch and manipulate ♪ Everybody sing along! ♪ Fitch, spec, it helps you ♪

[Transcript missing]

So, first time on stage, huh? Playing guitar. It was pretty noticeable too. So, if you guys ever want a repeat of this, let us know. And in case you didn't notice, James is also on stage inside the classroom on almost a weekly basis? A little less, but yeah.

Okay. So, if you want a little bit more information from him regarding EOF and other pieces of our technology, you can sign up for a WebObjects class. Great. Thank you. Go to the WebObjects lab and build one of these apps like Mark showed you. It will be very good. And roadmap.

We didn't talk a lot about using EOModeler here because data modeling and connectivity is all about that, which is groovy. Advanced Enterprise Objects Framework is going to be an awesome session. I'm going to be there because I love just always hearing more. And the feedback forum. And with that, who to contact? Looks familiar from every other session.