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-614
$eventId
ID of event: wwdc2001
$eventContentId
ID of session without event part: 614
$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 614

Advanced Java Client

WebObjects • 58:31

This session covers advanced features of three-tier Java Client applications, such as business logic partitioning, using delegates to encrypt communication between client and server, and controlling client access to server methods. Also covered are lesser-known features of Direct to Java Client and its use in applications that are not entirely dynamically generated.

Speakers: Andreas Wendker, Norbert Schatz

Unlisted on Apple Developer site

Transcript

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

So thank you and welcome to session 614. I know it's pretty late and you all want to get a hold of some beer, so I try to make it quick. The session is about advanced Java Client. I want to start out by summarizing a little bit what we heard in the session 609 and 606, and then want to go into a lot more details about the distribution there. So let me start by summarizing what we learned so far.

So Java Client is a technology for distributed desktop applications. It's a three-tier architecture. The client interacts with the user, displays the user interface. We use the Java Foundation classes or Swing for that, so we are basically platform independent. The server accesses the database, and the database is the third tier which stores the data.

The client never accesses the database directly. All the communication from the client to the database goes through the server, so the server has complete control over everything the client is allowed to do and not allowed to do. And also what's interesting to know is that the communication protocol between client and server, at least by default, is HTTP, so you get the connectivity of an HTML-based application running in a browser, but it's a much richer user interface. And Java Client is mostly designed for the intranet. There are a couple of complications with either the launch time or the amount of data you need to download or you need to client installation, so it's not a good technology for you to put on high-traffic internet sites.

Now, Java Client is actually pretty powerful, and it's very well prepared for a lot of advanced tasks. But since we do not have too much documentation at this time, a few of the features are relatively hidden, but I think you should really know about them. So I will try to talk about very concrete method names this time, notification names, and I hope that you can all take something away from here to really tune your applications.

So first of all, I want to go in a lot of detail about the distribution layer and the objects in the distribution layer. I want to talk a little bit about issues that you have to know about when you want to go into deployment with your applications. And if you save the time, I'd like to talk a little more about the controller factory that comes from actually the Direct to Java Client side and show you how you can use it to implement some nice features.

So, you've probably seen this diagram before. I don't want to go through all these boxes again, but I want to kind of point out about which of the pieces in this architecture I'm going to talk. First of all, the distribution layer is the layer that connects the client and the server. That's where I would spend most of the time.

And then at the end, if we talk about the factory, it would be in the e-generation layer right at the top. So let's start with some information about the distribution layer. And the most important topic when it comes to the distribution layer, to me, is business logic partitioning.

In Java Client, you can have implementations of your business logic both on the client and the server side. The business objects are fully functional on both sides of the architecture. And you have the choice to either use the same identical business logic Or you can use what we call petition business logic.

And petition business logic simply means that you use different implementations on both sides of the architecture. And so far, I always, you know, when I started talking about it, I said, you know, the first thing you can do is you can restrict the visibility of properties to the server side, so that they are not visible on the client side.

I want to make it a little more complicated for the purpose of this session, because you can also add additional properties that are only visible on the client side, but not on the server side. Now, how does that make sense? Well, you know, sometimes you're not interested in all the information, a lot of detailed information, you're just interested in derived properties. So let's say you have an object that stores dimensions, right, a width, a height, and a depth. And on the client, you really only want to see the volume of the complete object.

So what you can do is, you can add an additional property to your model, actually, and mark it only as a client-side attribute. And then you do not, and width, height, and depth, so the detailed attributes, you know, would stay on the server side, and on the client side, you only use a derived attribute. You also have the choice to use different implementations. So if you want to perform computations in different ways, the implementation of the business objects you use can be different.

First of all, that adds a lot of security to your application because you never send data or even implementations to the client that you don't want the client to see. Now with Java, you should probably know that all the classes you send to the client can easily be decompiled.

So if you have computations, algorithms that you consider secret, you don't want it to ever become public on any client side, then you can force the client to use an implementation on the server side. So you can force the client to make a round trip to the server, execute the computation there, and then just send the end result back. So no data and no implementation that you don't want the client to see will ever go there.

And business logic partitioning also helps you a lot with performance optimization, something that probably today with really fast client machines doesn't matter so much anymore. But if you have very fast server machines and relatively slow client machines, you can design your clients to make use of the computation power of the server boxes. As I said, it probably doesn't matter too much anymore. But what actually is important is that you can use business logic partitioning to minimize the amount of data that is transferred between server and client.

If you have computations that need to take a look at a lot of data, you need to fetch a lot of objects from the database to just get an end result. But you only want to display this end result. You don't want to send all the detailed data that you need for the computation. There's no need for you to send it to the client. You just design your client to make a run-through to the server, execute the computation there, and on the way back you just send the result.

And all the data that is needed for the computation does not have to be sent over the wire to the client side. I actually think that that's one of the keys to be successful with Java. You can use Java client that you find the right partitioning of your business logic. The key really is to minimize the amount of data that is transferred between client and server.

How do you tell EOF to use business logic partitioning? Well, you just go into EO Modeler. And if you want to use different implementations, Usually, well, you choose a different class. Usually in EOModeler, if you look at an entity, you have a column where you can enter a class name. With Java Client, you can actually, you know, unhide another column called the client-side class name, and you actually find it in this add column pop-up menu that you see at the bottom of the table.

And in here, you can specify a different class name. I don't know whether you can read it, but in the example that I use here, you know, the packages are example.common.creditcard in the first row, and it's actually the same on both client and server side. But, for example, in the second row, I use example.server.customer and example.client.customer. So, there are two classes, right, in two different packages, and on the client, I use a different implementation than on the server side.

The other thing you can do in EO Model is, if you actually look at the detail of an entity, if you look at all the properties and relationships, you're probably familiar with the column to set class properties. So these are the properties that actually make it into your business logic, your business objects.

And for Java Clients, you can again unhide another column. You can set the client-side class properties. So here, you know, you can, in this case, I actually restricted the clients, the visibility of the member since and the phone attributes. So they're only visible on the server, but not on the client.

The methods you use to implement business logic partitioning are defined in EU Enterprise Object. The most important one you probably need to know about is invoke remote method. That's the method you invoke on the client side, and you use it to basically move the execution of a method to the server side. So if you want to go from the client to the server, you use invoke remote method.

The arguments you pass are, first of all, the editing context the object is in, a method name, the argument types, and the arguments themselves. So this is, you know, the method name and the argument types identify the method that is supposed to be invoked on the server side.

If you invoke remote method, what happens is that the state of the editing context on the client side is basically pushed to the server side, to the editing context on the server side. And then the method that you specify with the last three arguments. Method name and argument types is invoked on the server side objects. So on the equivalent server side object.

And there are two more methods that are helpful for you. And they use them on the server side. And they evade from client update and prepare values for client. Those are basically notifications to the business object that something has happened on the client side, that the object has been updated on the client side. And you can use it to perform additional validation, or you can do computations. Basically, it's a notification that tells you the values for this object were changed on the client side.

And prepare values for client is invoked right before the object is sent back. When you send the result back to the client, Before the object is encoded to be transferred, we invoke prepare values for clients. If you have derived attributes that are only visible on the client side, evade from client update and prepare values for client are very useful.

You can basically delay the computation of the direct values until we invoke prepare values for client. Again, the order is, on the client side, you invoke invoke remote method. On the server side, evoke from client update is invoked. Then the remote method actually is performed. Before the object is sent back, we invoke prepare values for client.

There's a very important naming convention we use for remote method invocations. The naming convention is that if the name of the method starts with client-side request, then we considered a method that is open for unrestricted access from any client. If your method does not start with client-side request, then actually there's a security mechanism in place, I'll talk a little more about it later, that you can use to restrict the access of methods to certain clients.

Something that is now possible in WebObjects 5, but was not possible in WebObjects 4.5, is that now you can use common superclasses for your business logic implementations. In WebObjects 4.5 or 4.5.1, the server side was implemented in Objective-C, the client side was implemented in Java. In Objective-C, we had a wrapped API, so the superclass was in a server-side package.

So your generic record, your custom object, were in the server-side package, and the client had a different implementation of the superclass. So for a client-side business object and a server-side business object, you couldn't use a common superclass. But that's actually possible now, and that opens the door for a lot of good design, actually.

So what I recommend to you is that you use common superclasses for the two implementations, and just define methods abstract that you want to have different on both sides. And then you implement a client subclass with the remote method invocations, and a server subclass with the concrete computations. Let me show you an example.

So this slide shows roughly how a class secret would look like. This time I'm subclassing e-Generic Record. As you can see, the package there shows this example.com. I import comwebobjects.eu.control. It's just business logic. I don't need anything more. Then I would implement shared functionality, and all the methods that I want to have different, I declare abstract.

For the client side, I use a different package. The package is now example.client. And the class doesn't extend eugenic record anymore. It extends my superclass, the one that I just created, example.common-secret. And the implementation of secret value performs the remote method invocation. As you can see, I'm using our naming convention, client-side request, here, so that it's a little easier for me. I don't have to worry about the security restrictions then. And the method that I invoke takes no arguments. That's why 9 and 9 at the end of the invoke remote method, you know, if there are no arguments, you can just pass 9.

On the server side, again I use a different package, example.server. The class again extends the common superclass. And now the method secretValue actually implements my real business logic. As you can see, it's pretty complicated here. But then there's a second method. It's client-setRequest secretValue. So this is the method the client actually invokes, and it then invokes the real method. So this is the design pattern that I recommend to you. And this is convenient because you can write business logic, your code, against the abstract superclass, which is available on both sides. You don't have to worry about the concrete package.

If you want to reference the class from other classes, from other code, you would write it against the shared superclass, which is abstract. But since the API is defined already as abstract methods, you can compile against it, and then it happens to resolve to the concrete subclasses in the different packages at runtime.

Let's take a look at the objects that make this happen. There are four objects I want to point out to you. Two on the server side, Vue Java Client Applet and EU Distribution Context, and two on the client side, EU Distributed Object Store and EU Distribution Channel, or actually EU HTTP Channel, as we'll see later. The Vue Java Client applet is a WebObjects component. Don't get confused with the name that there's an applet in there. It's a WebObjects component living on the server side, and it's responsible for generating the applet tag.

It has a lot of bindings, some specific to the applet, like the width and the height, the code base. But it also has bindings really specific to Java Client, for example, the name of the application class, the name of the distribution channel, as you will see later. If you use Direct to Java Client, you have a binding that you can use to specify the class of the controller factory. And so the whole Java Client applet is the object. They basically represent through which all the communication from the client goes. If the client contacts the server, it actually talks to this object, the VoJava Client App that the WebObjects component that we instantiated on the server side.

Now, you might wonder how that all works if you start the client application as a desktop application, not as an applet, if you start it as a desktop app. Then actually we do create a whole Java Client applet. We don't really need it in that case, but we decided to do it anyway because it gives you one single place where you can configure your client.

We basically use the bindings of the whole Java Client applet that you can define to both initialize applets as well as desktop applications. So the advantage for you is you don't have to worry about whether your client runs as an application or whether your client runs as an applet.

It's the same code path that is executed all the time, and there's one place on the server side. In the code on the server side, we can initialize or we can specify all the parameters for the client. And usually, if you want to change some of the bindings, just open the main component, go into the WebObjectsBuilder in the inspector and change all the bindings there.

The other important object on the server side is the EU distribution context. The EU distribution context is the object that performs all the work when it comes to Java Client. It's the object that keeps track of a lot of state. It tracks which objects have been fetched by the client. It's the object that basically takes care of synchronizing business data on the client and the server side.

We could have made the Vaujava Client Applet and the EU distribution context the same object. That probably would have been pretty poor object design. Second of all, as you will see later, you actually have the choice to change the communication protocol. If you don't want to use our way of communication, if you don't want to go through a Vaujava Client Applet, you can plug in your own mechanism, and so you would still use the EU distribution context. The EU distribution context is basically the object that receives messages, but it just forwards it to the distribution context, and the distribution context is where all the work is performed.

On the client side, the two important objects are EODistributedObjectStore and EODistributionChannel. The EODistributedObjectStore is another type of root object store. It basically replaces the EU database context that you might be familiar with. The distributed object store acts as the parent object store for all the editing contexts. So when editing contexts fetch or save data, they go through the distributed object store. And the distributed object store basically makes the client behave like a nested editing context to the server side.

And every distributed object store, the distributed object store uses a distribution channel to actually perform the communication. So the distribution channel is responsible for sending the data from the client to the server. And your distribution channel is actually an abstract class, and you will usually use the concrete subclass UHTTP channel. But if you don't like it, you can plug in your own way of communication. I know that you all like pictures, so I have one for you.

So if an editing context, you know, on the client side, fetches data, it will actually go through a distributed object store, which will use the distribution channel to perform actually the communication with the server side. On the server side, the VoJava Client Applet, the instance of VoJava Client Applet that we created, is the object that receives the request.

It forwards it to the distribution context, and that one then, you know, usually accesses the editing context, the default editing context of the session, to actually, you know, take a look at the data. So the four objects that I introduced to you, the distributed object store, the distribution channel, the VoJava Client Applet, and the distribution context, those four objects work together to connect the editing context on the client side to the editing context on the server side.

Now that we know the distributed object store, there's actually an API I want to mention to you. The EU distributed object store can easily be found because it's the root object store. There's API in EU object store, default root object store. Is it that one? Default, root, parent? Sorry about that. You'll find it.

So it's actually very easy to access the EODC Build Object Store. And it has a generic API you can use to perform remote method invocation. So if you have something you need from the server that is not related to business logic, something that you need in your application logic, maybe information about what kind of resources are available, maybe you want to handle user defaults in a special way, then you can use this method here. And it takes similar parameters than the one that we found on EO Enterprise Object. It takes an editing context, the reason I'll talk about in a minute.

It takes a key path that actually identifies the object on the server side that receives the method. If you invoke it on an Enterprise Object, it's clear which object is the receiver on the server side. Because there's one version of the business object on the client, one version on the server side, there's an equivalent on the server side, so we know exactly where to send the method. But for the generic API here, you have to specify where to send it. The other arguments, method name, argument types, and arguments, we already know. And there's another flag, push changes.

So the method, the arguments, editing context, and push changes, I think you will probably not need them very often. But if your remote method invocation is related to some kind of business logic, you can pass an editing context, and this method here will make sure that the state of that editing context is synchronized with the server-side editing context.

Andreas Wendker, Norbert Schatz So if you need the latest state of the business logic of the business data on the server-side, you can pass the editing context, and for push changes you'd pass true. And then the distribution layer would take care of synchronizing the state of the editing context you pass to this method here, and the editing context on the server-side.

Let's take a look at the key path for a moment. There are three ways you can describe the target of the remote method invocation. First of all, you can pass just null for the key path. If you do that, the distribution layer assumes that you want to invoke the method on the distribution context directly. It's pretty rare, and on our default mutation of your distribution context, there's probably nothing you want to invoke. But if you use subclasses of distribution context, this might come in handy.

More common is probably that you pass an empty string. An empty string indicates to the distribution layer that you want to invoke a method on what we call a distribution target. The distribution context on the server side has a registry for arbitrary objects. You can just add additional objects to a registry. And when there's a remote method invocation, the distribution context will search through these targets and find the first one that implements the method you described and invoke the method on it.

So these invocation targets are a very convenient way to basically extend the functionality of the distribution context. There's nothing, the object can really be arbitrary, you know, any class does just fine. It just has to implement the method you want to invoke, and the method has to be public, by the way.

Now the question is, how do you register additional targets? Because, you know, while the server is running, there are multiple clients that are instantiated. There's not just one distribution context. For every client, there's a distribution context. So to help you, we send out a notification, and it's called EO Remote Method Receiver Needed Notification. It's a very long name, so use copy-paste.

If you register for this notification and receive it, you can use the notification to add your invocation target. So basically, you could make, for example, your application object. You can register your application object for this notification. And then in the notification, the user info dictionary, you would actually find the distribution context that was just created. So when the client connects to the server, you would send out this notification, and it would contain the distribution context. And then you can use it to add your method receivers. Yes.

And if you don't pass an I, and if you don't pass an empty string, then the distribution layer assumes that the key path actually identifies an object relative to the distribution context. For example, it could be a session, right? A distribution context has a method session. So if you specify session, you know, we would follow the key path, the string, interpret it as a key path, starting at the distribution context.

You know, go to the target and use that one as the method you want to send the, that one as the object you want to send the method to. Again, even for this generic API, we use the naming convention client-side request. So if your method name starts with client-side request, it's open for unrestricted access.

We'll talk a little bit more about distribution channels. As I said, the distribution channels are responsible for transferring the data between client and server. And as I said, there's an abstract class e-distribution channel, and there's a concrete subclass e-HTTP channel. You will probably, on most of the cases, you will stick with the e-HTTP channel. If you don't like it at all, you can implement your own subclass of e-distribution channel and use that instead.

It's fairly complicated, so if you can, try to stick with the e-HTTP channel. If you want to change the class of the distribution channel, there's a binding in the Vore Java Client applet that you can change, and there you can specify the new class name that you want to use.

On your HTTP channel, there's one method that is particularly important, because if you want to do things like connecting through SSL, you can override this one method here, createSocket. You pass the protocol of the URL, the host name, and the port number to create a different kind of socket, for example, an SSL socket. Now, I'd actually like to show you an example running through SSL, and I'd like to ask Norbert Schatz to come up on stage and drive the demo for me. So if you could switch to the demo machine.

For our demo purposes here, we used a package called JSSE that you can download from Sun's website. It's basically some kind of a reference implementation for a secure socket layer. And we have the code that we had to write on the client side for the channel here on the screen. So as you can see, there's a class SSL channel extending our UHTTP channel.

And if you focus for a moment on the createSocket method, we first check whether it's actually using HTTPS. If not, we just use the superclass implementation. So this distribution channel actually supports both protocols. And if it's HTTPS, then the only thing we have to do is to use the JSSE classes to create an SSL socket.

[Transcript missing]

Okay, I think now we'd just like to run the application just so that you know that it works.

So the server is starting. And so far, we obviously used this Java Client Launcher program. I think it's minimized in the dark, so it's at the right side. This time we want to show you actually the script that we're using. So we wrote in a script, and it's very simple. It's based on the script that WebObjects generates for you anyway if you compile Java Client applications.

We always create a launch script for you for the server side, but we also create a script for the client side. We just use that one. And then the difference is, if you pass in the URL, as you can see, we use HTTPS. And if you pass additional arguments, which is just channel class name, and there's our new channel class. So let's execute the script.

And hopefully in a second we will see an application that we just generated with the assistant. It's nothing fancy about that application, but it connects to SSA. So there's actually not a lot of code you have to write on the client side to make that happen. It actually turned out to us that it's much more complicated to configure Apache to allow us to do SSL than to implement the client side.

[Transcript missing]

Let's switch back to the slides. Thank you. A lot of features, a lot of the hooks that you need to use are implemented or available to you in the form of delegates. There are two objects where you can set a delegate to. One is on the server side, one is on the client side again. On the server side is on the EU distribution context.

There are various delegate methods you can implement. Just to list what you can do. First of all, you can encrypt and decrypt the communication. So every byte that is sent between client and server, you can apply your own encryption mechanism to. I think it's probably more convenient for you to just use SSL or something like that. If you want to implement your own encryption mechanism, you have delegate methods where you can control every single byte that is sent between client and server.

You can also control the access of the client when fetching business objects. Basically, there's a delegate method where you can control exactly which objects the client's allowed to fetch. So if you don't want to make objects of an entity visible to the client, you can just delegate and just say, no, you can't see that. Sorry.

The third hook you have in the delegate is that you can restrict the invocation of remote method invocations. If you don't follow the naming convention clients at request, then by default we do not allow the clients to invoke any other method. But you can use the delegate to open up the method invocation.

So for every remote method invocation that the client tries to perform, the delegate will be notified and can, on a client basis, determine whether this method can be executed on the server or not. So those are pretty strong security features here. On the client side of the e-distribution channel, you can also handle encryption and decryption, but this is the other way around. Both client and server obviously need to work together, otherwise you get a lot of mess.

So, the second piece is, the second hook in the delegate of the distribution channel is that you can deal with exceptions. There are two types of exceptions you can get. One is an I/O exception, something went wrong with your communication, right, maybe you can't open a socket, you know, maybe the network just went down, something like that. If there's an exception like that, the delegate can handle it, it can try to reconnect maybe, but it's up to you.

But there's another type of exception that happens quite often, and that is that something on the server, right, there's nothing wrong with the communication, but there's an exception raised on the server side. Maybe a validation error, right, maybe a validation method on the server side, the business logic on the server side raised an exception.

[Transcript missing]

The timing is pretty important for setting the delegates, because especially if you do encryption and decryption, you have to make sure that the delegates are in place before the first byte is transferred. The delegate needs to be in place on both sides of the architecture.

So the best way for you to set delegates is on the server side by registering for another type of notification. It's the e-distribution context instantiated notification. You send it out whenever we create an e-distribution context, and there you can set a delegate. And on the client side, the best way for you to set the delegate of the distribution channel is by using a subclass of your application and going to the constructor.

It's really the only place that you have to plug in your own logic before we make the first round trip. If you don't do encryption and decryption, you can do it later. But if you use encryption and decryption, then you would have to use an application. your application subclass.

I'd like now to talk a little bit more about deployment issues. First of all, I'd like to go over the system requirements. For the server side, a Java Client server application is a standard WebObjects application. Wherever you can deploy a WebObjects server, you can deploy a WebObjects server for a Java Client.

On the client side, the only thing we require is JDK 1.3. That does contain Swing now. That was different in earlier times, the JDK 1.1.8. Now JDK 1.3 contains Swing, so there's no need to download it anymore. On Mac OS X, Mac OS X is probably the best platform to deploy Java Client applications because JDK 1.3 is integrated in the operating system, very convenient. On Windows, you would have to download it from some website. And unfortunately, on Mac OS 9, there's no JDK 1.3 support, so you will not be able to deploy there.

The two options you have with Java Client for deployment are desktop applications or applets. If you deploy as a desktop application, you will create a little launch program. On Mac OS X, you will probably use Project Builder, or there's another tool called MRJ App Builder. On Windows, you will probably just create a little launch script and then create a shortcut to it from the desktop.

If you deploy as an applet on Mac OS X, again, it's relatively easy. You would probably use Internet Explorer, which comes with the system. And browsers on Mac OS X use the Java VM that comes with the operating system. That's pretty nice. On Windows, for both IE and Netscape, you would probably be required to use the Java plugin.

For IE, Microsoft has not committed to JDK 1.2 or 1.3 support. I think Netscape has, but it depends on the version of Netscape that you use. So the best way around this is to use the Java plugin, which Sun provides. Again, it can be downloaded from Sun's website. It's available to everybody.

And Java Client is actually pretty smart about this. It uses JavaScript to detect the client configuration. So we do the right thing for you. You can just say, yes, please use the Java plugin. You'll find out that if it's on Mac OS X, you don't have to use it. It's integrated in the operating system. If it's on Windows, for IE and Netscape, you do the right thing. Users will be pointed automatically to Sun's website. They can download the plugin, and then everything is fine.

Just to show you how easy it is to create a launch program, I'd like to ask Norbert to come up again. And what we want to do is we want to create a launch program for the application we just generated, the SSL that we just demoed before, the SSL demo.

And that's actually pretty nice because we can demo a few features of the new project builder that come in very handy. So the first thing we do is we create a new project. And this time, we just choose a Java application template. It's not even a WebObjects template. You give it a name. Call it SSL Launcher.

And this is a pretty simple project. It has a Java class. It has an icon file, so you can drag in your own icon if you want. This is the default IKB we get. And there's the properties file. And we will go ahead and change some of these properties. Actually, we already wrote them.

[Transcript missing]

Let's take a moment because there are actually a lot of classes that need to merge together in one Java.

[Transcript missing]

And it won't look very different from before, but the nice thing is now we have a desktop application. It's self-contained. We can take this one app. We can ship it to the client. That's all we have to do. Very nice. What's happening? There it is. So there's our client. Nothing special about it. Okay, thank you, Norbert. Could switch back to the slides.

Okay, I'd like to go again to the deployment options and compare the two deployment options. This is basically going to be a repetition of what we've heard so far, but I think it's very important to understand. So the biggest advantage of an applet is the simplicity of the client installation, because when the applet starts up, it downloads all the classes from the server side that it needs to execute the client program.

So if you want to upgrade your application, if you want to ship a new version of the client, you just have to install the new classes on the server side, and when the clients start up the next time, the applets, they just pick up the new classes, so that's very convenient for you to handle.

With applications, you first of all have to create this launch program, and then you have to install it on the client. And on the client, you have to have all the Java classes available on the client side. So if you want to upgrade, you're in a little bit of trouble because you have to make sure that all your end users upgrade to the new version.

So the advantage of the applet is really that installation and upgrading is so easy. On the other side, the applications provide a much better user experience, which is much more convenient for the user to have a desktop application that can be accessed through an icon on the desktop that is completely embedded in the desktop environment. You can hide the application, you can minimize windows, you have access to service menus. You don't have that with applets. So the user experience... is much nicer.

Also, applications perform a little better than applets. That's mostly because applications run very isolated. Applets in one browser, multiple applets in one browser actually share the same Java VM. So they can have all kinds of negative side effects, both on the performance and the stability side. That's not something you would be happy about as an application developer.

But applications are isolated. If another Java application is running, it doesn't affect us. If it crashes, if it does something bad with the system, it doesn't affect the Java application. Also from your perspective, as the application developer, you don't have to deal with security restrictions on the client side.

In AppLess, there's a security manager in place that usually prevents untrusted code to access the file system. But applications, you don't have to worry about that because there is no security manager. You can do everything you need to do on the client side. End users might see that a little different, and that's why it's got a little dot here.

Because, you know, with AppLess, they know if it's untrusted code, that the Java VM will prevent the AppLess from messing around with the computer. So they might actually like to execute AppLess. This other side, if you're in intranet environments, it probably doesn't matter so much because hopefully your end users trust the system administrator to pass out good software.

The last thing that can come in very handy with applications is that you have full control over all the Java VM parameters. If you need a special heap size, or you actually want to choose the VM you want to execute in, you can do so with applications and applets. You don't have any control over that.

A good compromise from my perspective is, when it comes in regards to installation and upgrading, to use a special class loader for the client application. The base system doesn't change that often. The base system would be the JDK 1.3 and all our UF Java Client classes. So it's actually a very good idea to install those classes on the client side.

And then to download all the classes that are specific to your application. That's actually exactly what we do with this Java Client Launcher that we used in the previous demos. We didn't have to configure the client in any special way. The reason was that it contacted the server first of all, asked it what kind of classes are specific to this client, downloaded those classes even before it went into the EUF code.

So that's very convenient because the base system doesn't change that often. It's on the client. But you still get a fair amount of upgradability with the special class loader because you can upgrade the client classes on the server side. You can make it available on the server side. And you only take a small hit because there are usually not that many specific classes to your application.

It's maybe 50 classes or so. And that's pretty quick to download. So you probably take a hit of one to three seconds at startup time. But the benefit for you to be able to upgrade the client applications quickly and fix bugs in an elegant way without having to worry about shipping another installer and making sure that all the clients really install it, that's quite compelling.

The next two points, session timeouts and server instances, I receive a lot of questions about that. So Java Client on the server side uses normal Vose sessions. When the client connects, you create a Vose session object, and sessions time out. That's usually not a problem, except that users of desktop applications usually don't expect that. I mean, if I'm running an app in a browser, I can understand why a session time's out. But if I use a desktop application that I just double-clicked, I don't usually see this concept of session timeouts.

So to help you, Java Client explicitly notifies the server if the user quits the application. So what that means is that if the client is terminated cleanly, so the user chooses the quit command, then it will actually make a round trip to tell the server, hey, I'm gone, and the server will then clean up that session.

So for most of your clients, you shouldn't have to worry about the session not terminating, because it will explicitly notify the server. The only sessions that might stay around is if maybe the network connection went down, the user decided to kill the application, something like that. So there might be a few sessions of not-cleanly terminated applications that stay around, but that shouldn't really bother you. So the best way to leave the session timeouts is to use event.

So that's a very large timeout, maybe 24 hours, maybe 48 hours. That way, users that started the desktop application, started in the morning, then maybe they went for lunch, come back three or four hours later, maybe had a few meetings in between, but they don't face session timeouts, and it shouldn't really concern you that the sessions are around.

Let's talk about server instances for a moment. With Java Client, you can scale the server side in the normal way, like with every other WebObjects application. If you serve a lot of clients at the same time, just use multiple server instances. I'd like to give you a little more information so that you can better understand what's going on with clients, some information that might help you to determine how many server instances you need. The first thing you should know about Java Client is that there's usually a very high load at startup. Often there are classes that have to be downloaded, especially if you run as applets. If you use Direct to Java Client, there's some kind of UI information being exchanged.

Also, users usually start out in the beginning to search for objects they want to work with. So there's usually a high load at startup, and then afterwards, it's usually just relatively small packages. And actually, for the same amount of data, the communication with Java Client, the package size for the data, is much smaller than the HTML.

So if you have five objects you want to display in HTML, or the HTML around it, if you compare that to the encoded data, the encoded stream of data that we use for Java Client, the Java Client stream is much more compact. It's really nicely compacted business data.

Now, the fact that the packages are smaller doesn't mean that you will never have a problem with communication. And what I would like to point out is that usually, in intranet applications, the amount of business data that the client wants to access is much larger. Andreas Wendker, Norbert Schatz Okay, and I think we actually do have enough time, so I'd like to talk a little more about the Controller Factory.

The controller factory is the object in the center of Direct to Java Client's dynamic user interface generation. It's the object that's responsible to communicate with the server to request a description of the client-side user interface. It's responsible for instantiating all the controller hierarchies that we use on the client-side.

But the controller factory is not only useful in dynamically generated applications. You can make use of it. It's actually very convenient sometimes to mix dynamically created user interfaces and statically generated user interfaces, so libfiles that you generate in the interface builder. The factory provides-- A good amount of API that you can use to retrieve additional configuration information from the root system.

[Transcript missing]

There's also more low-level API to retrieve what we call primitive controllers. You can consider a primitive controller to be a small unit in the UI, basically related to one entity and one task. So, for example, in the query window, you usually have a little query primitive controller and a list primitive controller. Every query pane in the query window will usually consist of two primitive controllers.

And there's a pretty large API. I just listed a few methods here. Query controller with entity, list controller, and form controller with entity, which you can use. And I'd actually like to show you how you can use these methods to implement some nice features. So Norbert is coming up again. Could we please switch to the demo machine? So here we have a prepared application, and I think we first want to start it.

So the server started, and now we use the Java Client Launcher again to launch the client. So we're connecting to the server now. See, the nice thing about this Java Client Launch is that we can even launch the client before the server is there, because it will wait until all the classes are downloaded, right? It will wait until we connect and then download the classes, and then start, then jump into the real EUF code.

So here's our application. It looks pretty normal. Why don't you move that window a little more to the left? And it looks like basically a window we could have created with the Assistant. There's a special menu item in this application that we added. It's called Configure. And we get a configuration tool, which happens to look very similar to the Assistant that we usually use. Now let's just have Norbert play around a little bit there and see what happens. So he's removing some of the attributes there. And then he's switching to List.

OK, doing the same thing there. Now watch the window on the left side when we press the Apply button. So the UI automatically actually configures to this new layout. So what we kind of simulate here is a UI where the end user can actually choose what kind of data he or she wants to see. It's like a user-configurable UI. Let's take a look at the source code we had to write for that.

So why don't you quit the client? OK, that's fine. So the class, interesting, is JC dynamic, which is a subclass of UI Interface Controller. And that's all the code we had to write. So the important method here is update user interface. We invoke it both in the constructor of the interface controller, and it's also invoked when we press on the apply button in this tool, in the configuration tool. And as you can see, the only thing we do is if there is already an editor, we remove the old one. then we create a new one that we have with the controller factory.

And actually, the primitive controller, you know, it's one controller with multiple subcontrollers. It's a little hierarchy of controllers that is responsible for, you know, this editor part. And we search the list controller in there. So we use a method on EU controller. It's called controller with key value pairs, which this is a method that walks through a hierarchy of controllers, you know, and looks for a matching controller for this key value pair.

And then we just set a relationship path. So that's basically the connection of the list controller, you know, the detail controller to the master interface. And we add the subcontroller. So that's all the code we have to write for that. So the controller factory is really useful for you if you want to have some kind of user configurable UI.

And why don't you press on the JC application. So this is code that would be much more complicated for you. You would obviously have to come up with a real tool for the user to enter the configuration data. But we made it easy. We just used some kind of a simplified assistant here.

And the most important piece, actually, if you scroll up again--

[Transcript missing]

So just to repeat what we did, if you want to come up with a user-configurable UI, you would have to actually use the rule system. I mean, we would use a dynamically generated piece in the user interface.

So you would have to write a rule to retrieve the list of properties the user really chose. So you would have to create some kind of a database, a configuration store. It could be in the file system. It can be in the database. And in the interface file-- oh, actually, sorry. I forgot about that.

Could we switch-- do you still have that open in IB? Just close. Okay. It doesn't matter. What we did in the interface file is we basically created it with the assistant and then just removed the whole lower portion of the lib file and replaced it with an empty box with an NS custom view. And we told the interface controller that this is the so-called sub-controller area.

The sub-controller area is a way for us to point the controller to a view where all the sub-views of dynamically generated UIs should be placed. And so we have to write a rule in the rule system to retrieve the list of properties on a user basis. We would have to go into the interface file, basically remove everything that we want to create dynamically.

We would replace it with an empty box. And then we have to write a little bit of code that dynamically swaps sub-controllers. And as I said, we use the API in the factory to retrieve primitive controllers. So for example, this controller with the entity. And then obviously, and probably the most complicated part, you would have to write a tool, like a preferences panel, so that the user can configure the data.

It's fine, don't worry. Okay, so in summary, Java Client is very powerful. It's prepared for a lot of advanced tasks. The most important objects are the EODistributionContext on the server side and the EODistributedObjectStore on the client side. I also mentioned the VotJavaClient applet and the EODistributionChannel. I think most of the time you will not work with them directly, but you use the EODistributionContext and the EODistributedObjectStore and the delegates for those objects. Distribution channels are customizable. It's actually pretty easy. It's your sort of plug-in SSL.

Again, you have multiple options to deploy. You can deploy as a desktop application or as an applet. And the controller factory is a useful thing to look at, even if you don't want to leave the traditional development. If you still want to work with interface files and generate most of the pieces of the UI by hand, the controller factory might make your life easier.

It's really worth to take a look at it. Okay, I think typical slides at the end. The lab actually closes now. It's open tomorrow again at 10:30. Please vote for WebObjects as the best app server. Those are the persons to contact: Tony, our director, and Bob in product marketing and iServices.