Tools • 1:06:34
This session provides a comprehensive look at building dynamic HTML components using WebObjects Builder, including essential component features and the tools used to build them. Understand where HTML meets the dynamic world of your Java application.
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.
How many of you made it to the keynote this morning? Good selection? All right. Got some very cool things happening. We're very excited with the power of our hardware to give us the potential to do even more deployments on Mac OS X, although of course we're always continuing to support pure Java deployments with everyone else. Was everyone here yesterday, pretty much? Or at least tried to squeeze in here yesterday? My name is Ernie Probacher. I am the product line manager for WebObjects and development platforms.
It's our pleasure to welcome you to the second day of the WebObjects track. It's two down, 16 to go, for those of you keeping score at home. And we have some really exciting stuff for you today. Just one quick note, we do want to try and keep the aisles clear. There are a number of empty seats here. I'm sure these are all real friendly people.
If you're standing in the aisles, please come and grab a seat. Or not, please grab some seats in the overflow section, because we need to keep the aisles clear so the fire marshal does not get very upset at us again. So, with that I want to turn the stage over to -- oh, James. James Dempsey, one of our trainer extraordinaires, and he'll explain to you about the very cool stuff happening with WebObjects Builder. Thank you very much.
Thanks a lot, Ernie. Good afternoon. I am James Dempsey. And let's see how this all works. Great. I'm a developer trainer with Apple Eye Services. I am much more used to talking to a room of 17 to 20 developers with a big whiteboard behind me and every once in a while asking, are there any questions? Today, I may slip up and say, are there any questions? I don't mean it. Just wait and hold them until the end, please.
Because I can't even see your hands, really. Actually, I can see your hands a little bit. So the first thing I wanted to do is just find out how many of you attended Steve Heyman's session yesterday, the technical overview? OK, which is most of you. Terrific. I don't know if you noticed, but in that session, Steve managed to cover just about every new feature in Web Objects Builder in 4.5, which is what my session's about. I'm just going to tap dance for you. No.
Actually, it's actually very good. Steve had a lot of great stuff in that presentation, a technical overview that kind of gave you a very quick, brief look at how Web Objects works. What we're going to do today is twofold. We are going to take a look at Web Objects Builder.
But Web Objects Builder is a tool that you use to create something called components. And components are really the heart and soul of a Web Objects application. So we're going to take this time in this hour, in this session, to go through very specifically and find out just what's going on in Web Objects.
We're going to go start at a high level, get down to the nitty gritty. And then we're going to take a look at the end at the new features in Web Objects Builder. So I probably should have advanced the slide already. We're going to talk about components. We're going to build some components using Web Objects Builder. And then finally, we're going to take a tour of some of the new features.
Okay, that's also what you're going to learn. So in a WebObjects application, the heart and soul of a WebObjects application is this request response loop. If you don't understand that, you're just not going to be a very good WebObjects programmer. So let's just start from the top and walk through at a very high level.
We have a client web browser, we have a web server running on a machine, and then you have your WebObjects application running typically on another box. Now, for the web server to talk to the application, we provide something called the WebObjects adapter, which is a CGI that is going to just route the requests from the web server to the application.
So generally things are going to work like this. The web browser clicks on the URL of your application, in comes a request, the web server passes it to the adapter, the adapter passes it to your application, your application processes the request, creates an HTTP response, stuffs it full of stuff, typically HTML, and sends it back, and the user gets a web page.
That's one go-round of the request-response loop. All your application does is sit there and do that over and over and over again. If in a desktop application, your application has an event loop that's just sitting there waiting for the next event, keystroke or mouse down event, same here, we're just listening on a port for that HTTP request to come flying in so we can handle it and send back an HTTP response.
So, let's take a, we'll drop out that infrastructure and just focus in on the application itself. Now, another difference between a WebObjects app and a desktop app is that in a WebObjects app we can have multiple users. Actually, here we have two. We can scale up to thousands, millions of users.
Here are represented two users by two different browsers. And we need a way to keep track of different users' stuff essentially. So, when a new request comes in from a user, we create, or the framework creates a session for that user. And a session is an object. You add instance variables to the session as places to hold the user's stuff.
It might be their shopping basket, their preferences, their personalization info. The request gets routed in, processed, and a response gets sent back to the user. The other user shows up. This is a very small, low volume site here. It gets processed and sent back. Now, how do we keep track of this? It happens automatically for you. Every session has an ID. That ID is either stuck in a URL or it's stuck in a cookie. Your choice.
So now we have kind of the general infrastructure of what's going on in a WebObjects application. We know how the request comes in. We can keep everybody's stuff separate using sessions. But we still don't know what's really going on, because sometimes you come to a presentation and you get all these arrows flying around, but you don't know how does that really work. That's what we're going to try to do today. And what's really interacting with the user is something called a component.
If there was a movie, the WebObjects movie, the component would be one of the leading roles. Everything we've seen so far The only reason all of it exists is so a component can do its job. All of that infrastructure is there to support the component in interacting with the user. So components, a little bit important. Okay, now how does a component interact with the user?
It does so in three basic steps. There are three things that a component always does to interact with the user. First thing it does is it generates some HTML out for the user. And there it goes. It gets stuffed into an outgoing response, I should say, and the user gets some HTML that they can interact with.
So the component starts the interaction with the HTML. Then the user interacts with that HTML. In this case we have a login page and Fred is going to log in, type in his password, submit it. It might be hyperlinks, something you click on. As soon as you click on something or submit a form, it sends a request, gets routed back to the right session, and finally back to the same component that originally started this thing, that originally sent out the HTML.
So now the component has two more things that it needs to do. It started this interaction. Now it's got to finish it. The first thing that happens when that request comes back in, our second phase, is it pulls any form values out of the request. So in this case Fred typed in his name, the password is the name of his cat, and what happens is that gets stored, typically in a variable somewhere.
When the component is done with this phase, it's going to start to interact with the user. So the component starts the interaction. Now it's got to finish it. So in this case, we're now certain that all of the state that the user typed in in the browser is now synchronized on the server side, which leads us to our third and final phase.
The last thing that happens is a method is invoked. This is the wildcard phase because it's a method that you are going to write. It's a standard method, just a function for you procedural folks in the audience, just a standard old method that's going to, do whatever you want. In this case, that method might go check Fred's username and password. You could also fetch things from the database, validate credit card information, take whatever the user is looking at and put it up in their order so that they can check out later.
You can associate one of these methods for every item that you can click on in the web page. And since it's a method that essentially gets executed based on a user action, we have a special name for these in WebObjects development. We call them action methods. And that's it. That really is the core heart and soul of WebObjects programming. That is all there is to it.
The rest of the time you have free. Go away. That's it. No. There's just a little more. But honestly, that is what's going on. A component generates HTML, lets the user interact with it. If there are form values, it pulls them out. And then it invokes this action method.
There's one missing wrinkle though. This is one interaction. How do we move on and interact with another component? And the answer is very simple. That action method has one particular requirement, which is it has to return the next component that's going to interact with the user. And there it is.
So that very last line in the method is going to say, return some component. And at that point, when we end that method, we no longer care about that old component. It's yesterday's news, who cares? That's the last request that came in. Now the golden child of the request response loop is that component, this new component.
And now it's going to interact with the user going through that same process, beginning with generating some HTML. And this page welcomes Fred. It's a very, very-- we could take this app and go out and get an IPO within six weeks, I'll become very, very rich and famous. Doubtful. OK.
So-- Let's review those again. Why? Because that's all that's going on. Steve Heyman yesterday talked about a steep WebObjects learning curve. I always think that it's steep not because Any one particular thing in WebObjects is really hard. It's just that there's a lot of it. But if you sit down and kind of commit these to memory and what order they happen in, everything else you learn in WebObjects on the web integration side is really just a refinement of these phases, an addition to these phases, or some variation on this theme. So it's a very nice framework, conceptual model in your mind, on which you can hang all the other pieces of information of WebObjects off of. So again, they are: you generate some HTML.
User interacts. In comes the request. If there are form values, the component pulls them out. And then finally, invoke some action method. And that action method is where you're going to write a lot of code, your custom processing. That's kind of the "you write your code here" part of this whole deal. And finally, we have to return the next component to interact with each user.
So that's the conceptual piece. Each of these maps to a method that is sent automatically to your component so that it knows when to do this stuff. And those are append to response is sent to a component to tell it to add its HTML into this response, take values from request, and invoke action.
Now, it's important to note, you don't send these messages. They're automatically sent to your component in the process of this request response cycle. However, as you start doing WebObjects development and start chatting with WebObjects developers, they're going to be using these terms all over the place and say, "Well, after append to response, then I'm going to put this header into the response and blah, blah, go on and on and on." It all just stems from this.
One other note is that we have been, or I have been talking a lot about this word component. And we know that the word component really, it's a very overloaded word. In many different venues it means many different things. So let me be very specific, very precise. In WebObjects when I say component, there's a class in the framework called Woe Component.
And that is the class that implements those methods: Append a response, take values from request, invoke action. It's also the class that implements those methods: Append a response, take values from request, invoke action. It's also the
[Transcript missing]
By convention, the first component that a user interacts with is called main, as we'll see as we build a project.
But of course, for every page that you want generated, you typically are going to create a separate component. The only thing you need to be concerned about is they need to be uniquely named. And so here we have the main component, and then in our former example, moving to a component named welcome page.
Now since the request response loop's really all I got, we're going to go through it once again very quickly. Quick review. So the user clicks a URL in their browser. In comes a request. A session is created. A main component is always created. It is sent to PenderResponse and so it generates HTML. The HTML flies down to the browser. The user fills out the form, submits it.
In comes a request. A side note, this time around Fred typed in the wrong password. We'll see how that's going to show up later. All right, the request comes in. The component's told to take values from the request. It pulls out the values, stores them in a variable, is then told to invoke an action. And that action determines-- our custom code determines, hey, Fred typed in the wrong password. We don't want to let him go on to the welcome page.
We want main to have another shot at interacting with Fred. Maybe-- A slightly different page with an error message or one of those red asterisks turned on to let Fred know that he screwed up. And so the convention in WebObjects is instead of returning a component at the end of that action method, we return null. We say, nope, you're not getting a new component. I'm going to re-interact with the user. And so in that case, if we return null from that action method, the same component instant gets used again.
It sent a Pender response again and it starts its interaction with the user. And now Fred has a slightly different login page. Alright, let's build that. So if we switch to number four. It's like magic. Great. All right, so we'll start in Project Builder. Make a new project. Call this thing. No assistance. Java is our language.
And if we look at the classes in Project Builder, you'll notice some familiar items. There's the application that we had seen before, the session. And there's also main.java. And I described a component, in this case main, as a class, as a type of object. And you'll see that indeed, main extends woe component. And it's a very boring component at the moment. It does not have any additional instance variables or methods. We're going to change that in a moment.
but a component is more than just a class. There are two other files that describe or make up a component. They're stored in web components in a .wo directory. And there's an HTML file. And that HTML file is a template that shows what main is going to look like.
And then we know there's a Java file that defines all the state that we can store in main and all of its behavior. And there's a third file called a bindings file, which is that connection between the user interface and the state. We're going to talk about those and look at those in a little more detail. For now, we're just going to open up main.wo in WebObjectsBuilder, the other star of our show.
Great. So, for those of you who are relatively new to WebObjects, WebObjects Builder, the top half is an HTML editor, a graphical HTML editor. So we could type in some static stuff. Please log in. And of course we can make it bold and... nah, we don't want to center it. Make it larger, change the font... beautiful. We don't want to center that either.
And we're going to put in a form. This bottom row are items called dynamic elements. And these are object-oriented placeholders of where something dynamic is going to show up. So username,
[Transcript missing]
and a dynamic submit button. Okay, we've now built our award-winning user interface. And now we're going to have to worry about where are we going to put those values when they come in. This bottom panel is called the object browser. And if we notice, the first column is labeled main. And in fact, this column is a graphical representation of all of the values and all of the methods that are in the main class.
Now you'll notice that we have two already there: application and session. However, the main class, there's nothing between those curly braces. Every single component is able to access its session and application automatically. It's behavior that's gotten from the superclass Woe Components. However, we do need a place to stick the username.
And we can add and edit that Java file right from here. We'll add a key called username. It'll be a string. And we only need an instance variable for that. And it adds us here. If we take a look at the source code, you'll notice that indeed it has added that instance variable to our source.
And it works in both ways. So if I type something in manually, like my other variable that I need to store the password, when I head back to WebObjects Builder, it shows up. So there's a direct correspondence between this column and the code In the component that I'm editing. Now we need to connect this text field so that the values here show up in this variable.
To do that we just drag on up and every dynamic element has a bunch of attributes. Required attributes show up in red if they're not already bound. So we're going to make the value of this text field get stored in that variable username. Do the same for password.
And there we go. So, we're now worried about, or now we're done with the state storage. The only thing we need to do now is get to the point where I can click on that submit button and go to that welcome page. So let's add an action. We will call it login.
Hey, hey, We're going to add it. And notice that it's added this login method here. There's a line, everything above the line you can think of as a value. Everything below the line you can think of as an action method. We're just going to hook that up to the submit button as its action. and we're ready to roll. Let's go take a look at that source and notice that it has indeed added a method. We're going to add one line of code. This line of code automatically creates and initializes that welcome page. The next line of code.
We're just going to pass the username along to the next page so it can display it. So set username to our value of username. So wait a minute, you may be thinking, where did Welcome Page come from? And why does it have a method called setUserName? Well, at the moment, there is no such thing as the Welcome Page.
We're about to create it, and we've got to make darn sure that it actually has that method in it. So let's set about to do that right now. Web Components: File, New and Project. We'll call this Welcome Page. No Assistance in Java. And then we'll open it up in WebObjects Builder.
Alrighty, we're going to need a place to store that. Username, string. We're going to generate source for the instance variable and methods, accessor methods as well. We'll add that. Let's build our user interface. Welcome. We're going to add a dynamic string element and hook that up. Now let's make all that really big. We'll center it, change the font, change the size.
Change the color, great. View the source, and it has indeed added that instance variable and accessor methods. That's all that we need to do. So let's build and run. You'll notice, what did we do, really? We defined two HTML pages, some very basic ones. We added a couple instance variables, a couple accessor methods, one of these action methods that's automatically generated for us, and we typed in one line of code.
So let's take a look. Username, Fred, password. Oh no, our password field is in a password field. Not a problem. One of the very neat things about WebObjects development is-- let me minimize that-- is that a lot of it is not compiled code. For example, our HTML template is not compiled.
So we can come into WebObjects Builder, select something, and inspect it. And a text field, well, an inspector has all of the attributes that you have set or not set, and all of the bindings. We can switch to a static inspector, and in this case, turn our text field into a password field.
And let's say we want to change the Submit button so that its label says Log In. Well, in 4.5, we can double click on an item to have the inspector show up. And we'll change the value. to login. We can type in a literal value instead of having it go to get some method or some variable. I would just save our change, minimize main, and when I refresh, it automatically updates, which is pretty nifty.
Password. And we're welcoming Fred. Now, let's just take a moment. To go through blah blah blah that request response loop. So, as soon as I click this return button and that URL comes in, we make a new session, main is created, main is sent to Pender Response, it generates its HTML.
We put in a value, login. As soon as we hit login, that request comes in. The username and password are pulled out of the incoming request. Our login method is executed. It creates a welcome page, passes the name along, and returns it in that final phase. We're now done with main, and the welcome page starts its interaction by generating its HTML, and we get a dynamic page. Any questions?
Let's go back to main. Steve showed you this yesterday, but some of you might not have been here. We can switch from a nice GUI editor to raw text mode. The HTML is just plain stock HTML with the addition of a WebObject tag. One additional tag that says, "Hey, something dynamic is going to go here."
WebObjects Builder: A WebObject tag is one attribute which is a name, a unique name, and that name maps to an entry in this second file, this bindings file, where we find out, hey, that WebObject tag, what kind of thing is it? Is it a form? Is it a dynamic submit button?
And also, all of those attributes that you saw in the inspector, they are all present here, so that that dynamic element knows where to get its information or where to put information at right. So, that's the runtime. Okay, done with the demo. Let's go back to the slides.
If you understand that, if going through those three phases by now bores the dickens out of you, then that's good. That means you're well on your way to becoming an excellent WebObjects programmer because that's what's going on. That's pretty much it. There's additional stuff that hangs off of that, but that's the whole shebang for the web side. The next session is going to be talking about the database side. So if it's in your head, beautiful.
However, you might be saying, well, first of all, let's talk about the stuff we didn't have to do. We didn't have to do anything, if you noticed, to get all that to work. We could take what we just built, if we wanted to, deploy it on a whole bunch of 16 processor Solaris boxes, and let millions of people show up and type in their name and have a page come back that says, "Welcome."
It wouldn't be terribly exciting, but we could. We didn't have to do a whole lot. We didn't have to touch the request. We didn't have to touch the response. We didn't have to parse the form values. All of that just happened for us because that's the stuff that you have to do every single time.
That's the stuff that, who wants to be bothered? So WebObjects takes care of that so you can write the cool stuff, the logic, the application logic, the business logic that makes your WebObjects application useful, unlike the application I just wrote, and also gives value to whoever's going to be using it. However, we're going to dig one layer deeper and talk about what's really going on here. How does it do all that?
Well, I showed you those two other files. We know there's a Java file that defines the object, but there are these two other files: an HTML file and a WAD file, as it's called. I always find that just a weird word to say, "Wad file." Everybody say it. WAD file. Say it loud. WAD file. Say it louder. WAD file. Even louder.
[Transcript missing]
So when we're generating HTML and append to response, what's going on? Well, the component has this template. And when the component is told, hey, append to the response, well, the component says, well, I don't know what to do. Hey, template, append to the response. And it goes through, and the static stuff gets popped into the response. Then the woe string is told, hey, append your stuff to the response. And the woe string is like, well, what am I? Oh, I've got to figure out what I'm going to put in here, I guess. And it does its thing.
And then there's more static stuff that just gets thrown in because it's not dynamic. Then the hyperlink is told to append to the response, and it has to figure out what URL it's going to use, and so on down the page. So every dynamic element gets its shot at appending its little chunk of HTML into the response.
Let me go back one. Just a note, each of these items, when it builds this nice little template, has a unique element ID. So whenever a hyperlink, for example, generates the URL that you're going to click on, that element ID is in there. So it can tell, oh, I was the thing that was clicked on. And whenever a text field is generated, it has a little name attribute that is the element ID. So it can look into the request and say, oh, that's my value. No real magic going on.
Appender response, when it's sent to a woe string, it says, oh, OK. Well, I belong to a component, and a dynamic element without a component is useless, utterly useless. They work together. So when a woe string is sent to appender response, it consults its bindings, says, oh, my value is hooked up to username. Let me ask my component, what's the value for username? And the component gives back the answer. In this case, Fred, the woe string goes, oh, now I know what to generate in the HTML.
That happens for every single item in the template. If there were 18 bindings, it would go and ask 18 different times. For taking values from the request, when the component is asked to take values, it just turns to its template of dynamic elements and asks them to take values from the request. Of course, only in this case the text fields are going to find something there. So what's going on? Well, we have our components. To start off with, the username and password have no value. And in comes a request.
Books in, takes that value Fred out of the request, consults its bindings, "Oh, my value's hooked up to username. I'm going to tell my component, 'Hey, take this value Fred for that key username and store it there.'" And so it happens. And that happens for every form value. That's all that's going on. And then finally, invoke action. In this case, we know the submit button was clicked. How does that work? Well, the request comes in.
We have a component with some action methods defined, in this case login. It reads in that URL, it's what flew by real quick. Let's do that again, this is fast. consults that, says, "Oh, my action's hooked up to login. I'll send my component login." And then the component executes that method. Let's execute it again. Do you know how long that takes in PowerPoint? That's a real pain to do. Do it one more time.
I just love that. That's what's going on in WebObjects. That's it, actually. There's a couple other details I'm leaving out, but this is the absolute core. The absolute core of what's going on in every WebObjects application. If you have this firm in your head, You're pretty much good to go. You're on the right track. You can go downstairs to the lab if you're brand new to WebObjects and start building the little pup that I just started building. Now, two points that I want to make, and those two points are this.
It's kind of interesting that we can get to a dynamic element can get to that information in the component, but we have this thing called a session. And it's kind of odd that if main needs the username and the welcome page needs the username, that we have to write all this code to pass it from page to page. What if like eight components needed to get to the username? Well, we might instead stick it up in the session.
And every component can get to its session, and every component, and then in the session we could store it in one place for each user. Now how would we hook that up? Well, what's very nice is we have something in WebObjects called a key path. If you recall before, right, if value was hooked up to username, it would ask its component, hey, what's your username? And it would get back a value.
Well, we have this dot separated path, and so when this woe string needs to find its value, it asks its component, hey, what's your session? What's your value for session? Then it asks the object that gets passed back, hey, what's your value for username? It gets back the value, and voila.
Kind of nifty. Those paths always start with the component, however. But let's go one step further, because a username is not a very useful piece of information. A username, actually, most websites, my username is like JD17234, because all the good ones were taken. Does anybody have a good, nobody does. There's like one James and that's it.
Welcome JD 1472. Here are the last five purchases from our site. We want to group things together. So in the database I might have a row that has the username, maybe their password, maybe it's encrypted, a first name, a last name, an email address, maybe a relationship to the last five purchases, favorite color, all that good stuff. Using the database chunk that's in the next section, we can take that row in the database, turn it into, in this case maybe a customer object, and store a customer in the session.
And a customer is going to have different properties. In this case we're going to use first name as the example. And to hook this up, we're going to use the Just a longer key path. Just kind of whisper down the chain. This is seven degrees of Kevin Bacon, is what I call this.
Because it's the same exact thing. It's like, I'm at the component, what key path do I need to get to the information I need? And this time around, it's just going to ask, hey, component, what's your session? Hey, what's your customer? What's your first name? And then get back the answer.
This can be arbitrarily long. Like I've seen them eight, nine, they just go on forever. The important thing to realize, two points, is that each of those things, all the codes you wrote, you put in an instance variable. That's all you put in, was one instance variable to hold the next object.
You don't have any, all this accessor code where you have to pull the customer name into the component. And the other neat thing is that this path is not compiled at all. It's in that binding. file and we saw that if I make a change, that I just refresh.
I don't have to restart the app, let alone recompile it. And so if I want that string to hook up to last name, I just change that to session.customer.lastname, refresh the page, and then I can go back to the page. And suddenly I've made a major UI change with very little work on my part. Very little risk as a developer.
And now I want to say any questions, but I'm not going to. I think I just did. Oh, I'm hitting the back button. How scary. There we go. We're going to do a demo. What we're going to do is twofold. We're going to implement a little password checking logic and have an error message pop up if the person types in the wrong password.
Then when we're done that, get that working, we're actually going to hit the database based on the username, fetch the right customer object, stick it in the session, and on the next page, the welcome page, reach into the session and pull down their first and last name and display it.
Let's type in an error message. First let's make it nice and big. You have... That is not recommended Apple UI guidelines. However, haven't you all wanted to put that at one point or another somewhere in your app? You can applaud. I don't mind. I got extra time. Okay. And then we need, this is, oh, what did I just do? How about I explain what I'm doing in the demo? That might be nice. That would be a good thing. I'm adding something called a conditional. A conditional is an if statement in your HTML.
And it needs a Boolean to determine whether to show or hide what's in there. Well, we don't want everybody getting this rude message, so we're going to add a Boolean. We'll call it a login error. We type Boolean. We only need an instance variable. And we just wire that up to the conditional.
will save. That's all we need to do to our UI. Let's go to the source. We actually have to write a little conditional logic here. So, matter of fact, I have an extra moment. It's actually, where am I? There it is. No, that's not what I want. There are many, many wonderful preferences in Project Builder Woe. Okay, let's just bump up that size. Set it.
The first thing we're going to do is apply the syntax coloring. Okay, so here we go. Easier to see the code. So the first thing we're going to do is the next page by default, if they don't type in the wrong password, we don't want to let them see our super secure welcome page with all that sensitive information. So we're just going to return null by default. And then our elaborate password checking scheme, if the password they typed in equals the string password.
[Transcript missing]
The actual new page. And we're going to send that information along to the next page, the user's name. Else, if they screwed up and typed in the wrong password, login error, we're going to set that to true. We'll build this. Notice that what we're doing is taking some conditional action in that action method, because you don't have to return one component all the time. It's your code. You can return whatever the heck you want.
Let's go to OmniWeb. Let's log in. Fred will log in. He won't type in the right password. and now he feels really terrible because he's an idiot okay so fred if there any friends in the audience i very much apologize i You're not an idiot. This is a hypothetical, Fred. And if he types in the correct password... Login. There we go. Wonderful. Next step, hitting the database. So, let's actually minimize some of these windows.
Now we need to be able to hook up to a database. All will be explained in the next session, but for now, none will be explained. We add something called a model file. which is built with EOModeler, the topic of the next session. And we're going to build, or we're going to add a customer.java file which is generated from EOModeler, which is covered in the next section. So if you're curious, go to the next section.
All right, web components, resources, put everything in the right place, that's very good. Now, all that we're going to do is this. We're going to first... Change this. We no longer need the username here. Very nice new feature in WebObjects Builder now. In addition to adding stuff to your source code, you can actually delete it.
So we're going to delete the username. It also is going to check to make sure that these bindings that you have set, do you want to unbind them or ignore it? Well, we're going to unbind. So it keeps you from having errors due to binding. We'll add a second string.
Now another nifty thing in WebObjects Builder 4.5 is when I click on an item in the first column, the second column is now a representation of that particular class. And actually if I have source code to it, I can even add stuff. So I can add stuff to the session. It's a contextual menu. I'll add a key to the session. I'll call it customer of type customer.
Let's have methods to get and set as well, which adds a customer from that customer class. It knows all the stuff that's in a customer, so we can display the first and last name of a customer just like that. Now let's, actually we'll minimize that. Who turned on window shading? I had the other behavior set. Okay. Now let's edit this pup. Login.
So when they login, we want to fetch. There is a, actually, we're going to fetch a customer. We'll call it customer as our local variable. And in Java, we're going to typecast what comes back as a customer. We are going to use an EOUtility, which is a very quick one line way to fetch in WebObjects. EOUtilities can't talk one thing and type another thing. We're going to go ask for the object matching key and value.
In WebObjects, in your application, every session by default has this place where you can edit and fetch objects from the database called an editing context. So we're going to use that to perform our fetch. The thing that we're going to be fetching Our customers are going to be looking up customers based on their username. The actual thing that we're going to look up on is what the user typed in for username. That line is going to go get us a customer. Do I need it? Oh, you're right. Thank you, Mr. Compiler.
No, because that's how I code. I let the compiler deal with those because it's good at it. Better than I am, apparently. So here we go. Customer. And now all we're going to do is check if the customer... No, that's not what we're going to do. If the password that they typed in equals the customer's password... Then we're not going to pass anything along. We're just going to stick that customer up in the session.
So we'll access our session and tell it to set its customer to customer. So in addition of one, two, three lines of code, let's see how this This seed of a personalization engine is working. So, let's go back to our good friend Fred. He'll type in the wrong password. We don't let Fred in. He types in "whiskers," his correct password. And voila, we have our personalization engine. Let's get another session going.
Brand new session. This time it will be JD12345 Let's type in the wrong password. Voila. And so we have two different sessions, two different customer objects fetched from the database. And we didn't do a whole heck of a lot, did we? I built that in, I don't know, 10 minutes, 15 minutes. Now is that production code that I wrote there?
No, we might want to check to make sure that we actually got something back from the database. We might have encrypted passwords. Stop by the security session later this week to find out more about security and login issues with WebObjects or techniques. However, boy, if you're going into a client, this is a nice prototype, right? You whip up very quickly, so that's pretty groovy. Again, we did A fair share of stuff here in a very short amount of time. And let's switch to the slides actually.
We did it all without doing all too much work. We added a couple instance variables, added a couple accessor methods, we added one action method that took some conditional action and did a little bit of checking. We set some things, we got some things, and we did some mysterious database stuff which will be explained later.
With that, what I'd like to do is, now you have a good idea of what the heck is a component, how does it interact with a dynamic element, or its dynamic elements, how do these three files, this HTML file, this WAD file, this Java file, how do they interact, what's their relationship, how do they interact at runtime, and how do they interact with each other?
Where do I plug in my code? What are the things I have to worry about? What don't I have to worry about? So at this time I'd like to bring up Tom Naughton from the WebObjects Builder team, who's going to talk a little bit about new features in 4.5.
Thanks. I think my leg has gone to sleep, so if I fall over, don't mind me. Anyway, I'm going to talk a little bit about the new features. The goals in 4.0, first of all, how many people have used the new 4.5 builder?
[Transcript missing]
Syntax coloring. Previous versions didn't have syntax coloring, but we didn't just want to add it to make it pretty. We wanted to actually make it useful. So it's actually kind of smart syntax coloring. It'll show lots of times when people edit HTML by hand, they'll introduce errors, like mismatched tags and such. So the syntax coloring actually shows you the errors.
Whenever the tokenizer runs into something that it doesn't like to parse, it'll make that token red. And if you, let's see, add an extra closing tag that doesn't match an open tag, it'll draw that in red. So basically you can just look at your page, you can see that tags are unbalanced, and you can easily fix the errors.
Improved Binding User Interface. Let's see, people liked the way you can just drag connect your bindings in the builder, but in previous versions you'd have to drag up, select the element, and then go over to the inspector and actually click which binding you want to bind to. So it was a little cumbersome. We made it, we changed it so it's, you can do all that in one gesture. You just drag up, a menu pops down, you choose the binding you want to connect to, and it's all very fluid.
Improve font tag support. The built-in font panel that you get from the app kit is real convenient for picking one font but for HTML you usually want to specify a list of fonts so that the browser can use a different font if it doesn't have the one that you specified. So we added a font panel custom-made for HTML. It saves all of your font preferences so that you can use them again and again.
Display options. Let's see, okay, one important thing we added was a preview mode. We're always torn between do we want to make the builder what you see is what you get or do we want to add lots of convenient editing widgets. And by adding the preview mode we can actually do it both ways.
If you choose preview mode the builder makes all of its rendering decisions in favor of making it look just like it would look in the browser. If you choose editing mode it shows you all of your bindings, it shows all the web objects and the binding values on them. There are lots of convenient editing features. You can also turn on the preview mode.
You can also add options and preferences so that it will show things that are otherwise hidden such as HTML comments or JavaScript so that you can get a better view of what your page actually looks like and then switch to preview mode and it will again show like it looks in the browser. And we also added an API editor.
We've had API files in previous versions of the builder. It basically exports which bindings are available for nested components. But previous versions of the builder didn't use it very well. You had to edit the file by hand and users didn't adopt them very well. So we actually added some UI to make it easy to make the API files. And you can also add your own binding validation rules just like the built-in validation rules. So it makes it a lot easier to set up those files.
Anyway, I guess James has a demo now. He's going to show some of the new features. Alright, we're up to the... whoop, do I need to click? Oh yes, because I have to put up the very important demo slide. Okay, we got the two minute warning, so let's fly on through this.
So let's take a look at main again. And I'm just going to kind of walk through some of the features that Tom had talked about. The first one being that we can delete bindings. So, username is hooked up. We'll delete that. We'll also unbind. All well and good, but then I say, "Oh, I didn't mean to do that.
I got undo." And this undo is not only going to re-hook up everything correctly in the bindings file, but it's also going to put that thing back in my code in Project Builder. So, it's aware WebObjects Builder is editing three files at once. This undo is actually keeping those all up to date. Very nice new feature, because I always make mistakes. I don't know about you all. Every once in a while. Contextual menus.
We have them everywhere. Actually, you'll see them as they come up. We're a little pressed for time. Let's add a new table, take a look at the table panel. We open it up. We get to pick how many columns and rows we want, border, etc. My favorite, most handy thing is that your second row can be automatically wrapped in a repetition, so you don't have to select it and add one, because you're always repeating lists of things.
And your first row can be automatically header cells. We're going to add just a plain 2x2, and let's move our form elements in there to neaten things up a bit. Where am I? Help! Okay. We'll just re-hook that up. See, even when you totally screw up, it's even easier in WebObjects Builder 4.5.
I'm just demoing somebody screwing up in WebObjects Builder 4.5 and quickly recovering. So there we go. Well, open the inspector. We no longer have to switch to some sort of--well, first, this is the path view. And it's very nice. I want to select the table. Bam, I've selected the table. Very easy. To edit the table, I don't have to go to some structure editing mode. I just click in the inspector, add a new row. Let's merge these cells together.
Let's move the login panel or the login button in there. That's wonderful new stuff with the table view. On the palette, You have, well, Steve Hammond's leftover palettes from yesterday, but also JavaScript palettes that ship with the product, including image flyovers. We'll just throw one in there. Definitely check out these JavaScript reusable components. They're very useful.
And there's also validation. So you'll notice as soon as I drag that in, this button came to life and told me that something screwed up on my page. I have validation. I have some required bindings of this image flyover that I have not hooked up. The other nifty thing is if I click on the error, it automatically selects the item that's having the problem. So if you have 18 hyperlinks on your page, you can jump right to the right one. So we're going to fix our validation problems by deleting that.
If the feature don't work, cut it. Let's close up the palette. Let's jump over and let's look at this HTML editing. Nicest thing, well two things. One is, say we screw up our HTML somehow. Notice that this closing tag has turned red to indicate that something has fouled up. And so it's doing error checking that's very obvious in color.
We also have a very nice feature. If I triple click, it'll select all the way to the matching tag. So we double or triple click this table, it'll select to the other end of the table tag. Even niftier, if I triple click and drag, it'll select ever enclosing tags all the way up the page and all the way back to where I originally clicked.
Here's a nifty feature. Some folks like to put comments in their WAD files. WebObjects Builder 4.0 is notorious for, when you go into graphical mode, getting rid of your comments. Well, we can type in some comments, switch back, switch back. They're still there. That's a very good thing. You can applaud that one.
This is a golf game. Good. Thank you. Some other nifty things. In the inspector, say we want somebody to type in a date into a field, we can put date formatters. That's always been there. But you had to remember these formatting strings. Well, now there's a pop-up of common formatting strings and examples for date formatting and number formatting.
Makes life easier. That also is true of many types, like Boolean types. If you're picking an action, you get a list of all the actions in your component to choose from without having to remember or type them in yourself. So those pop-ups are very nifty. And, oh, one of my favorites.
It's always kind of hard, or it's always been hard if you wanted to wrap a repetition around two rows for some reason. Well, there are a lot of these new display
[Transcript missing]
is very, very easy. Now you say, well, that's great because I want to see how my table's laid out, but this don't look like a table no more. Well, that's why preview mode was added. So it's going to look like rendered HTML, whereas you can have all of your nice editing widgets.
[Transcript missing]
And to thank this man gave up a lucrative career as a stand-up comedian just to become a WebObjects trainer. Thank you, James. We're going to start the Q&A now, so we invite anyone in the overflow room who wants to come and ask questions to come up and join us.
Again, please try and use the microphones in the aisles so that people getting interpretation and recordings will be able to hear them appropriately. I also have the other presenters up here, if we could, to help answer questions. Thank you very much. I also want to introduce Ben Haller from the WebObjects Engineering team, who will be joining us as well. Ben Haller: Tom, the QA is left.
Oh, do you want to mention the roadmap real quick? Sure, let me answer that. All right, so roadmap. Next section is on the database chunk. Two sessions from now is deployment. You've built your app, now what do you do with it? It covers the new deployment architecture in 4.5. Later this week, integrating client-side technologies, i.e.
JavaScript and all sorts of other nice stuff, Smile, QuickTime, Flash. Reusable components. Now we know what a component is, let's make them so that we build them once and reuse them in project after project. And I also did mention that security one, which didn't fit on this slide. For more info, there's that thing downstairs, the big lab. Check it out.
[Transcript missing]