Tools • 33:16
This session provides information on the goals of Java in WebObjects, and the migration of Objective-C applications and frameworks to Java. It includes issues, tools, process, and deployment challenges.
Speakers: Francois Jouaux, Ben Trumbull
Unlisted on Apple Developer site
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
This is going to be a fun one, talking about Objective-C to Java transition issues. So please give your undivided attention to Francois Jouaux. Nice to meet you all today, and this is going to be the most soporific hour of the day, so bear with me and we'll make it exciting. I know there are a lot of Objective-C zealots this afternoon in the room. Can I have a show of hands? Oh yeah. So, don't worry, I brought a bulletproof vest. And let me introduce my bodyguard, Ben Trumbull.
Yes, and we have Riot Shields in the back. And Ben, by the way, will be doing the demo for us today. Okay, so what are we going to cover? This session is going to assume some previous knowledge of WebObjects. Obviously, if you've been programming for years in Objective-C, you know about WebObjects. We are going to cover all the different strategies for converting Objective-C, WebScript, and Bridge Java projects. And we are going to demo all the supplied conversion tools.
What you'll learn will first make a stop and go back on the goals of the pure Java release named WebObjects 5. will then go in detail into who should convert, who should not, and what API and feature changes you can expect in WebObjects Pure Java. Then we'll move into the conversion process per se, and give you some hints on how you can expand it.
So what is this WebObjects 5 release called WebObjects 5 for Java? I never understand why there is this for Java afterwards, because it's in Java anyway. It is basically WebObjects 4.5 ported to Java. It is a full-featured WebObjects 4.5 compliant, and all the framework, WebObjects, EOF, WoE extensions, you name it, are there. It works as an add-on to WebObjects 4.5.
For example, all the developer tools are shared between 4.5 and WebObjects 5. The monitoring tools have been ported, and the test tools have been ported as well, so that you can use them. You can use the pure Java version of these tools to either monitor or test the 4.5 apps or the 5.0 apps. This is a good way for us to provide bug fixes for these tools at the same time. And finally, there is the conversion tool we are going to talk about today.
So what are the benefits? One of the most important benefits is that it still runs where we used to run. You can still develop a Mac OS X server on Windows, and soon you'll be able to develop on Mac OS X. The deployment platforms have been extended, and we now support Linux deployment environment.
We expect to have a smaller runtime footprint by moving to Java and to let you deploy on a lot of different platforms that we can't even think of. We're looking forward to someone deploying on PlayStation, for example. I don't even know if they have a VM for it.
Other benefits: Well, you can expect, and take my word for it, a better Java experience. WebObjects 5.0 is going to run on JDK 1.1.8 by default, and will be JDK 1.2 and 1.3 compliant. We are not going to take advantage of the newer VMs, just for backward compatibility, but we are going to run on them.
This release will allow for much better integration with third-party development tools. We have already some experience using optimizers and debuggers that are outside our usual development toolbox. And finally, we'll integrate much better with any third-party products that provide the Java interface. No more bridge issues to be concerned about. More benefits: Database connectivity is going to be expanded. Now that we have a pure JDBC support, we are providing a plug-in technology so that for vendors that have a customized JDBC interface, we are able to support these customizations. We have also ported the LDAP adapter.
Okay, so when I showed marketing the prototype of the WebObjects 5 release, which was codenamed Monet at the time, from the French painter, They came to me and said, well, Francois, this is great, but what are we going to do with all our Objective-C developers that have hundreds of thousands of lines of code? Are you going to provide them a tool to deal with this? And I said, no way. I cannot do it. This is a task that is very hard and will never reach a 100% solution. But I went for it, and I spent some time designing, and spent a lot of time in the dark. Then I saw the light.
I came up with a very good design for a Java converter. My claim is that we are going to take you 80% towards a pure Java solution by using these tools. And by the way, there will be a Java Converter t-shirt, and guess what will be at the back of the Java Converter t-shirt? We'll have commented out this Objective-C return.
Okay, let's move on. Who should convert? Well, basically, any Objective-C or WebScript developer that requires more deployment solutions should consider converting. Anyone with an existing bridge Java application should not even consider it, should just do it, because it's going to be seamless. Anyone requiring access to more Java standards to better Java development tools that we do not provide should think about converting to.
Who should think twice before converting? Well, if you've been around for a long time, you've been used to take advantage of the Objective-C goodies that we like and that we are going to lose. So if your WebObjects application or framework contains tons of categories on our own NS*, Wo*, or EO* classes, maybe because you want to extend them, maybe because you want to fix your own bugs, you name it, well, you're going to be in trouble.
If you rely heavily on the PoseAs feature for the same reasons, PoseAs is a very powerful feature of Objective-C, and it is gone. If you use a lot of low-level Objective-C runtime calls, this kind of functions that you can find in the system.framework/headers/Objective-C header files, these are all not supported. You'll have to deal with the pure Java runtime, so runtime provided by the JDK and the Reflect APIs.
If you use low-level C function calls or structures, you're in trouble again. You'll have to change the structures into objects if you can, but if you don't own these C function calls, well, you'll have to find an equivalent in Java. And of course, if you're already in production with your application, it is in Objective-C, but you have deployed it, why the hell would you want to convert? Just let it run, let it bring you money by truckload, and concentrate on the future.
The conversion process. So what does it take? So my claim again is it will take you 80% there. Let's use a metaphor here. Let's assume you want to repaint your house. So you could go at it with a paintbrush and a bucket of paint and spend your summer painting your house. Well, that's not very exciting. Now, the other solution is to hire professionals, but professionals are very expensive.
We're in the 21st century, so you could hire a army of robots that would come, and because they are very basic robots, that would tape around the trimming and windows of your house and spray paint it. Now, they would paint a few bushes and trees, but what the heck? Your house is painted. And you're 80% there. All that's left for you is to remove the tape and do the finish work. It's interesting work. That's how Java Converter works. Okay, let's start with a demo.
my lovely assistant of the day, will demo the Java converter on one of our examples, the distributed session store application. So basically, this is a command line tool that is written in Java. And you see that it is first copying the project, and then moving through all the files. This is a fast G4, so it's really hard to talk as fast. Sorry for the Japanese translators.
Okay, did the job. Now, if Ben would like to open the project, this was a project with some web script and some on 1.m, so it's a very simple project. Ben, do you want to open the Java version, which is one of these? Yeah? So open the pb.project.
So you'll see that now you just have Java classes, and the application.m was changed into an application.java. You can click on it to show that there is some Java code there. And same with the other classes. If you look at the framework bucket, the framework bucket is now pointing to the new frameworks.
and so on. So I wouldn't claim that this code compiles, but all the grunge work is done. Now, we have another example. which is again doing the same kind of work, but this time on a file. The file we picked is the EOUtilities file. So open this and pick EOUtilities.m.
So, again, Java Converter is working on the file, and is going to come out with... At one point you see that there are some post-processing calls being done. It's part of the customization I talked about, and I will explain it in more detail later on. If you look at the files that have been created for us, you have two files: one is eoutilities.java, which is actually empty, Because most of these click on it, it should be OK.
Oops, you moved it. OK, click on this. Yes, this one is interesting. So this is actually what happens to categories. Categories are moved to static classes. You don't see the word static here. This is a bug. But basically, the methods that were in editing context, on AO editing context, are now moved to categories. And this is an important point.
Okay, and now as a last demo, it is a demo that is going to take much longer, Ben is going to start in the background the conversion of the whole, the whole extensions framework. So, this is a 5000 lines of code freaking framework with Objective-C, WebScript, Java, EventOnClientSideJava, and it's just going to go through it. So this is going to take a while. Let's move back to the slides now. And Ben, tell us when this is finished so that we can look at the result.
Okay, so what did you see? Java Converter has different modes of functioning. It has a project-wide conversion mode, a file-by-file conversion mode for touch-up work, and an all-at-once or rich-Java-only conversion mode. So what are the different steps you can accomplish? You can first move your files one by one from C, Objective-C, or WebScript to a pure Java file.
You can move a whole project directory to a pure Java product directory. You can move a product directory to an intermediate step, which is Bridge Java, which you can still run on 4.5. And then move it again to a pure Java product directory. And you could do the same with files.
So, why would you convert in one step? Converting in one step from an Objective-C to a pure Java project can be done for smaller projects. You can expect a long period of non-running.
[Transcript missing]
All your files are converted, and the resources, the makefiles, and the framework references are corrected. We need to slightly modify the component wordfiles and the direct-to-web models, for example.
Now, by the way, this one-step procedure is the one we took for our EO Access framework. The two-step conversion is a procedure I followed for the WebObjects framework itself. At the time, I didn't have a conversion tool. It came after a while. So I did the 20, 30,000 lines by hand. It was not a pleasurable experience. The way I made it more pleasurable was by porting classes files, classes, one after the other, and keeping the app running at all time. So this is doable thanks to the bridge.
You can-- we recommend this approach for larger projects, because at all time you keep your project running. You're just moving one file at a time from the Objective-C world to the bridge Java world. And you keep everything in sync. You make some APIs public if needed through all wrappers.
By doing so, you can do incremental framework conversion, and you can go down to a class by class conversion. When I started converting WebObjects to Java, I wasn't even sure it was going to work in the first place. So what did I do? I started by converting the dynamic elements.
And pretty soon I had a framework that was split between Objective-C, bridge Java, and I was applying it to an example like Hello World. And this was still working. So I grew more confident, and I ported the Woe Session object. Now I had the Woe Session object on the bridge side, and so on and so on, until one day all I had left was the Woe Application object. Now this object is the 5,000 line of code monster.
Again, here there is another approach you can take, which is to subclass this Objective-C Java and subclass it through the bridge in BridgeJava. And at this point you can move method per method, one by one, through the bridge, and again, makes the conversion process much more... It's stable, I'd say. You always have something running. It takes a lot more time. But if you have a manager breathing down your neck, asking you, well, Francois, where are you today? You can say, well, today I have the WoS session that is running, or whatever is your case.
And once running, your project can be converted to pure Java by using the Java converter again. Okay, so what does a resulting pure Java code look like? Well, let's pause for a moment. How do I look like now? I look like a clown. Okay, but I'm still myself.
I'm still myself, and your code is still going to be your code. It's going to look different, but the important part, the logic, the algorithms are still there, and they are still yours. So please, look further than just the language they are in, because this language conversion can be automated. What cannot be automated is the value you bring in the code, which is your own logic. And what we do is that we beautify your code.
Well, beautify to which standard? I'm a mellow person, and I don't care very much about aesthetics, but we have some people in our group that are very on top of these code standards, and they have defined or beautified code standards. Well, if you don't like them, use one of these beautifiers that are available on the web for Java code. There are about ten of them.
So pick your own, and make it look as you want. Now, we preserve the order in your code, of course, otherwise what would be left? And we prefer all your comments. We as well add some comments that are tagged so that you get three levels of conversion errors that are easily searchable in the produced Java code.
We're done, Francois. Wow, what a timing. OK, so let's look at our WebExtensions Java project. So this is a very big project with sub-projects. And the Java converter dealt with them correctly. Oh, here, actually, we have some more categories, interesting categories. Categories on objects that are not recognized, like NSArray, NSMutableArray, cannot be merged back into the model class, let's say.
So these categories are transformed into static classes. These are the four ones you see at the beginning of the project class list. Now, if you move to sub-projects, for example-- oh, you would like to see one? Okay, click on the first one, for example. So, it's now a helper class.
And I... and this method should actually be static, this is just a bug, we'll fix. Now if you move to the Subproject bucket, you see that we had a bunch of Subprojects. We had client-side Java code, well this was pure Java code, and we just didn't touch it, because it was already in pure Java. We had some more, for example, the more even... oh let's... The row event logging code is interesting as well. Pretty complicated code. Can you open one of these? Let's see.
Let's see what we can find here. So you see the comments are preserved. Yeah, it's not very complicated. So basically, these kind of classes, you can expect them to compile at once. Let's move back to the top level. I'd like to show a web script file. So classes, and look for the statistics page. I know this was a web script file.
For WebScript files, what you lose is the type declaration of the object. For all these IVARs, you get an object type. Whenever we can restore the type, we do. For example, you see here in the middle, there are mutable dictionary and double. Well, the Java converter is clever enough to notice that some arithmetic operation was done on this IVAR.
So it deducted that this should be a double. So it made it a double IVAR instead of just a plain object. So sometimes with WebScript, it's able to restore the type of an object. Other times, it will just leave it as an object. Okay, well let's switch back to the slide.
And let's move on. So once it is time to compile-- You go through all these errors and solve them one by one. And because most of the errors will be the same, you're going to be able to solve a bunch of them at a time, and more importantly, have a consistent way of solving them.
So the biggest problem I got when I did my file-by-file conversion, converting the WebObjects framework, was that A month down the road, I had forgotten what type of solution I had found for a problem on day one. And I tend to solve the same problems in different ways, and it led to very inconsistent coding. Now, when you have a tool that will do everything up front for you, it will solve simple problems like try-catch exception, wrapping of exceptions, and enumerations, and so on, in a nice and consistent way.
So, I claim that you know 80% there, and that I have taken out the hassle of converting. My translation rate, personally, was 300 lines a day. So, for example, this project of WoE extensions that sees 4500 lines of code, I would have done in 15 days. Java Converter just did it, just brought me 80% there in five minutes. So that's a pretty good accomplishment, isn't it? Okay, let's drill down more into the issues.
Some foundation classes are not available anymore. So don't run away screaming. These are the classes you were not using in the first place. Or you were using them because you had to, like NSAutoReleasePool. Who is going to mourn AutoReleasePool? We have some skeptics and some masochists here. Java lang thread is a good alternative to NSThread. Same with Java lang string.
So we removed NSThread, NSString, and others that had exact counterparts in the Java world. The NS* structs are gone, except NSRange. We kept NSRange because it was used in our public APIs, and we didn't want to break our public APIs. So we kept it. But if you're using NSSize, NSPoint, NSRect, you'd have to create your own Java object to do so.
Categories issues. Let's sum up what we saw in the demonstration. Categories on classes in the same project are reunited. So if you implement your own class and then lower down in a sub-project, you start adding categories on this class, everything will be merged in one class. So you will not be able to use categories to compartment your code anymore, like in Objective-C. Categories on external classes are transformed in helper classes, especially categories on classes like NSString.
But the new helper classes cannot be referenced when needed automatically, so you will still have to go back. Let's say you decide to have a category on any string and re-implement length. Now we are going to create, the Java converter is going to create for you an NSString under our length class with a helper method called length. But it's not going to be able to guess that everywhere in your code it's called length or not. So you will have to go and modify the call into a static call there.
Macros and Functions: All macros are resolved. This is done by using the C precompiler, and because of that, you may run into problems if you're using if-devs a lot to solve cross-platform issues. You may have to convert several times for every platform you're using. Exception handling is handled nicely. NSEnumerator is handled nicely as well.
Same with if statement, whether there is no test if the object is null or not. All the NSFunctions calls are gone, and these are automatically translated when we can. In other cases, we do not have an equivalent, so you'll be on your own. And finally, C-Function calls must be corrected manually. We do not provide a conversion command for fopen, for example.
Some more API issues. Most of our API changes are automatically done for you. And most of these API changes actually occur between Objective-C and BridgeJava. Between BridgeJava and PureJava, there is almost no API change. The change between BridgeJava and PureJava is just an import statement change. and a couple of API challenges, but very minimal.
So don't be too concerned about this. The API you're using 95% of the time will be there. So, as I said, all classes have kept their bridged API, and the API changes on your frameworks can be automated. I will explain, go more into detail on this last point later.
Okay, now, what happens when you start an Objective-C conversion? Basically, the Java converter is an Objective-C compiler. It's written in pure Java as well. But, and because of that, you cannot use the GNU Objective-C grammar. It's using a grammar that I have rewritten that is based on the GNU Objective-C grammar, and it follows a grammar standard from Metamata, which is a grammar used across Java, the Java world, for parsing. We provide this grammar so that you can improve it. If you want to support WebObjective-C syntax, like the @asm for assembly code, if you find a way to embed assembly code in your Java program, you have the grammar. You can do that.
This is not a good C compiler. I have concentrated on converting Objective-C to Java and not C to Java. If you rely a lot on C pointers and pointer manipulation, well, you're going to be in trouble. So don't use that to convert your C-based graphics library. It won't work. And as I said before, we use CPP for macro preprocessing.
Webscript conversion. Well, what is the best Webscript parser we have here? It's Webscript itself. So I slightly modified the Webscript parser. and extended it to generate pseudo-Objective-C. So once I get this pseudo-Objective-C code, I can feed it to the real Java converter that will change it into Java code.
That's basically how it works. So I had to loosen somewhat the Objective-C grammar so that it would accept this slack WebScript coding standard that you like. And finally, the Bridge Java conversion is done by just feeding a Bridge Java file to a top script, and the output is pure Java. All the imports are corrected, the minimal API changes are applied, and that's it.
Java Converter is extensible. What does it mean? As I said before-- well, I haven't said it before, but the source code will be provided. The grammar will be provided. And for people that are not that adventurous, we as well provide buckets, well, script folders, where you can drop your own scripts to enhance the pre- and post-conversion steps.
So if you have put a script in the pre-conversion folder, whatever file is fed to the Java converter will first be passed through this script, and the output will only be fed to the Java converter. And this way you can automate your own framework API changes. If you have your own API changes between Objective-C to Java, you most likely will, you can automate them with one of these scripts.
In conclusion, I went into more detail in the WebObjects 5 environment. We demoed you a great tool that handles much of the uninteresting work for converting. and the rest of the team will be present at the next session. I hope most of you will find a use for it, and that you will be very successful.