ActiveJDBC & ActiveWeb for Java w/Igor Polevoy

UGtastic Archive
Full Transcript Available 115 Minutes
Working in Java and want the hotness of Ruby on Rails? Igor Polevoy will show how to make your Java life easier and more Rails-ey using ActiveJDBC and ActiveWeb. ActiveJDBC is an implementation of ActiveRecord in Java, and ActiveWeb is a full stack web application framework in Java, both inspired by Ruby on Rails. Learn how to increase productivity in Java as well as improve code quality with true TDD/BDD.
The Interviewer

Mike Hall

Interviewer, UGtastic

The Guest

Guest

Guest

The Conversation


Mike Hall Interviewer, UGtastic
All right, so now that we're recording, I can say hi. Welcome to Software Craftsmanship in McHenry County. Everybody, this is Igor Polvoi. He's here to talk to us about Active Web and Active JDBC. They're his open source frameworks and tools that he started. But before we get started, you know, I just thought we did this a couple months ago. We kind of went around and said introduce ourselves at the end of the meeting. I thought maybe this month we could do it at the beginning of the meeting. So I'll just I'll start. Hi, I'm Mike. I founded Software Craftsmanship in McHenry County with Jim Succi and Ryan Jerry, who's not here tonight. You might have noticed that I have this very, very nice shirt on. It is that time of year again. It is wrapping up for Chicago Code Camp. We have a call for speakers out. It's also our CFP is up at chicagocodecamp. com. So I had to recommend everybody going here and submitting talks. And then registration will be open soon. Next month, I believe we're going to be doing micro frameworks with Luen and Min Meng. Please spread the word on that. Those guys are awesome. They've gone and done this talk that I can't remember. It was one of the major Microsoft conferences, but it was extremely well received. But they do this hands-on lab. So it's going to be really cool. Next month, so you know, I'll go on to the right. So Igor, you can introduce yourself and then Jim and then, you don't have to stand up if you don't want to. I want to be in the view. Hi, everyone. My name is Igor Falavoy. I've been writing software for a number of years and being mostly in a Java camp. So my presentation tonight is going to be about two open source frameworks that I developed in order to assist people to write applications, web applications, or just applications as well as web applications faster, be more productive, and basically write less code and be smarter. And, you know, everybody just feel free to, you know, whatever you're working on, whatever you're doing, whatever you want to promote, like, a certain thing that Jim's involved with. I'm Jim Suchi. I work at 8th Light. We're a consulting company in Libertyville downtown. I'm consulting downtown for a payment processor. I also co-organize the Chicago CrossFit Group, which we're meeting next Tuesday. And just so you know, Aaron Bedra is a Clojure superstar working for Groupon now, who's our sponsor for this month's pizza. And he's also the author of Programming Clojure. Second version. Yeah, let's do it all the way. So he's definitely one to pay attention to. Okay. My name is Daniel Richard. I'm actually not so much in the industry as you guys are. I'm starting up a company doing Android and iPhone development games and so forth. So next month, it's going to be... Well, actually, I was a business systems analyst in the 90s. I got started on 8-bit Commodore 64s way back when. Oh, yeah. So in the 90s, I was doing C++ C in the Visual Basic and I worked over at Alphorn Marine Corporation and how life changes things that went off into a whole other industry and opened up a detective agency and so forth. So now I'm getting the bug again with all this iPhone and Android stuff. It reminds me so much of, you know, the old days of programming the 8-bit machines. You know what I mean?
Guest Guest
Even though it's not 8-bits, of course, it's 90. They added one.
Mike Hall Interviewer, UGtastic
Jim?
Guest Guest
I'm Jim Taranski. I work for a company called Insight Development Group. We build a CRM and iPhone app for looping contractors. I'm trying to get into job development and Android development. So maybe we can expand on that. But also, personally, I'm just a lot of development. So we're just trying to learn something to code. Cool.
Mike Hall Interviewer, UGtastic
Yuri?
Guest Guest
My name is Yuri Kozarovitsky, and I'm a consultant for Follett Corporation, Follett Software Company. Oh. And I'm a J2E developer with different expertise in J2E areas. You're in this... Right here.
Mike Hall Interviewer, UGtastic
Yeah. Yeah.
Guest Guest
I like it. Good. Good. My turn.
Mike Hall Interviewer, UGtastic
Sure.
Guest Guest
I'm Sion. I work for Sears. I lead the mobile web development team there. I'm a front-end developer, also in J2E, but mostly HTML5, CSS3, JavaScript, and I was around. '90s, I was around '80s, but I'm not like it goes back then. Awesome. I'm Philip Birmingham. I work at Bino Harris Bank, doing nothing interesting. I'm basically trying to keep my hand in by coming to meetings like this, also doing personal projects, Rails, JavaScript, Canvas, HTML5, stuff like that. Just whatever seems like fun. That sounds cool. It is. It is. It is. It's a lot of fun. I'm working on something in Rails right now to set up a phone tree using Twilio because it sounds like fun.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
And that's basically it. Like I said, I'm looking to make a career change soon, or a job change soon. I just had an interview today, so I think I'll actually be coding professional. It's just a little insider tip. We had somebody from Twilio submitting talks to CodeCamp, so we will most likely have at least one session.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
All right. Excellent. Jeremy.
Mike Hall Interviewer, UGtastic
Jeremy, do you want to introduce yourself for me? Sure.
Guest Guest
I'm Jeremy. I work mostly in a non-individed job. I don't have an actual job yet, but I won't be interviewing at college. Oh, that's great. Excellent. That's exciting.
Mike Hall Interviewer, UGtastic
We can edit that out, right?
Guest Guest
No. No, I've done editing last month. Oh, now I got to go and log that in my food log now. I'm going to get busted. Hi, I'm Ralph Eiden. I'm a developer here at Polysoftware as well. I've been here for a while. Mainly do Java work, although in my other interests with embedded processors, Arduino, and PIC, and all kinds of different things, I have my hands on a lot of different things. So one of the things of interest to me that I'm working on now is a compiler design and I'm reworking for the nth time, an expression parser that is like the granddaddy of everything. It's just, you know, you just kind of hand it to anything and kind of knows what it does. So we'll be putting that up on the project board and that's all finished. It's interesting because that technology I wrote way back, probably in the early 80s, and it just seems to keep getting different generations. I was looking at my first Java version in 1998, and then we revamped it again, and it's not now. Now we got to really completely do this differently. So we simplified it. Cool. All right. Before I cede the floor to Igor and start, I just, I'm going to put out a call for help. You know, we, I promote the group as much as I can. I've got the meetup. com site now, which has been great. We have a few people who have learned about us through meetup. com. But the way people learn about us is a lot of word of mouth, blog, Twitter, you're at work, you're at work here. There's a lot of empty seats. This room should be full. But let people know about these meetings. We have really great content. We have Igor coming in, you know, from way out in the north suburbs. We need your help. You guys are the ones that are going to make this group really big. So without any further ado, I'll just go ahead and hand the floor with Igor. All right. Hi, guys. So active JDBC equals equals active record for Java. So the idea is this. So tonight I'm going to be presenting two with two frameworks that I developed over the course of several years. The first one is active JDBC. So active JDBC is active record for Java. You've probably heard that active record this and active record that. There's active record path, there's active record technology in Ruby on Rails.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
Some people call hibernate active record. One way or the other, active record is a thing that connects an object to a record in the database. That's the whole idea. So basically, any ORM, technically speaking, could be called active record. Now, however, the active record phrase probably has been more popularized by Ruby on Rails because of the way the ORM is implemented there. Part of the Ruby on Rails that actually does connection to, does integration between your code in the database, it's called active record.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
They just took the name of the pattern and applied that name to a framework. So I was doing Java developing for a number of years and I sparingly used Hibernate here and there. Mostly, you know, whenever I would have to do like a massive database project, I probably, I usually used just use just JDBC because I was kind of lazy of trusting my well-being into some framework. And nonetheless, Hibernate's been the staple of Java development for a number of years and it seems to be popular and working. But, if you look at the API and how to use the Hibernate or any other, you know, like second-in-command in Java would get IBATs, probably heard of that one too. If you look at their APIs, they're like, okay, all I want to do is put data in a database and pull data from database. Even using just JDBC, things seem to be simpler than with Ibernate or Iadaptis. For example, a few months ago, there was somebody started blogging about blogging tutorials on developer, on Dzone slash links, you know, how to set up a project with Iadaptis. And the whole world was to save something in the database and read that basically one table, one column, one insert, and one read. So that entire example was 200 lines of code. Properties, files, XML, and Java all together. It's just bothers me. So, a couple of things about me.
Mike Hall Interviewer, UGtastic
Who the heck is Igor Followyoy?
Guest Guest
I've been developing Java software for a number of years. I did C, C++ first, and then switched promptly, briefly to VV, and then started doing volumes of visual C++. When Java came out, basically I switched to Java, and I've been doing Java ever since. I've been wearing different hats. I've been a developer, an architect, a manager, back to developer, and then I'm all, you know, for the past five years, I've been all of them at the same time. Right now I'm working for Groupon. I also teach some Java and Rails types of all institutes of professional development, and I've seen a lot of IT projects. Some failed, some successful. All right.
Mike Hall Interviewer, UGtastic
So, the question is, why would somebody go and develop another ORM for Java?
Guest Guest
If you look, like, a database framework for Java, you'll probably find 30 or 40, most of which you probably haven't heard of. So, you've probably heard of, what, JPA, which is a layer on top of Hibernate, then you've probably heard of JDO, then you've heard of Iodatas, and that's it, right?
Mike Hall Interviewer, UGtastic
What else is out there?
Guest Guest
Oh, TopLink. But, you know, we can only count a few of them. But if you really look for open source implementation, there's, like, 20 or 30 more.
Mike Hall Interviewer, UGtastic
So, why would I want to create another one?
Guest Guest
Because when I learned, I intuitively didn't want to use many of them, or any of them, and I used just JTBC for years and years and years. And until I learned Ruby on Rails, I'm like, oh, my God, this is the right way to do integration with the database. So, dissatisfaction, you know, Hibernate is very powerful, but complicated.
Mike Hall Interviewer, UGtastic
How many people actually use Hibernate in their projects?
Guest Guest
All right.
Mike Hall Interviewer, UGtastic
Three people? Okay. What do you think of Hibernate?
Guest Guest
Very powerful, but complicated. Yes. Especially the configuration aspect. That's just nuts. Yeah, but sometimes, let's say, I was maintaining a project a couple of years ago that was on Hibernate, and we just could not understand why it wouldn't work. So, yeah, and then it turned out that somebody turned down a specific property in some property file that basically limited the size of every select to X number of rows. So, you think, you say, well, you go to the database and say, I have a hundred rows there.
Mike Hall Interviewer, UGtastic
Why is it returning three?
Guest Guest
So, things like that. So, GPA, different configuration for every platform. Again, GPA is just a small subset of Hibernate anyway. So, you know, there's not object created. I actually claim that they're not object created.
Mike Hall Interviewer, UGtastic
Why so? Why?
Guest Guest
Because all other frameworks, they require a third party class to operate on this class. So, you guys probably heard of a notion of anti-patterns.
Mike Hall Interviewer, UGtastic
There are patterns, things that we want to repeat, right?
Guest Guest
There are also anti-patterns, things that we repeat but we shouldn't.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
So, one of the anti-patterns that is classically represented by Hibernate is called an event data model. An event data model is when you -- well, basically, when you work with Hibernate, you create your entity. Then you create your DAO, then you create your DTOs. Then in your entity, you write a whole bunch of setters and getters. And that entity doesn't really do anything. Basically, for all intents and purposes, your entity is nothing more than a hash table. It's a bag of values that has no idea what to do with them.
Mike Hall Interviewer, UGtastic
And other code is responsible for upgrading on those DAOs, correct?
Guest Guest
I mean, that's what Hibernate feels to me. So, when you start seeing some ActiveGDPC APIs, you understand what I'm talking about. Basically, in ActiveGDPC, there are no third party classes. There are no XML files. There are no property files. So, it's absolutely clean. Basically, you write your entity in one line of code. So, DHH, David Henson is the guy who developed Ruby on Rails. I believe he's a great API designer. And the idea of writing an ActiveRecord is -- the ActiveRecord itself is pretty complex. But using it is very easy.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
So, ActiveGDPC follows the same principles. Also, ActiveGDPC does not provide every problem under sign. It only provides 80%.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
And then it stops. And basically, it says, beyond that, we basically will solve every common problem. Beyond that, we're not going to solve every problem out there because we don't know what they are. Well, it also depends on a simple schema. And usually, complicated DB schemas are either wrong design or some legacy they use. All right. So, if necessity is the mother, then the laziness is the father. So, you could say that -- although, I could tell you, writing something like that is no picnic. It is very complicated. So, there's the design principles. I mean, it's not complicated complicated. The entire source code of ActiveGDPC is not that big. It's about 15,000 lines of code. It is lightweight and fast. The JAR file is 120K in size, has no dependencies, works twice faster than HyperNate, and it doesn't require setup. All right. Step number one, or principle number one, should infer metadata from database. You probably saw HyperNate entities where it says, this thing is mapped to that table. This instance variable is mapped to that column. This instance variable has many of those things.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
One-to-many relationship. Many-to-many relationship. So, right. ActiveGDPC is absolutely free of that. You already have that data documented in the database. So, when you start up your project, ActiveGDPC goes into the database, reads the schema metadata, and configures itself accordingly.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
That's why it requires no configuration. Things that can be a little bit, they can look exactly the same, but in the data model. You can override. In ActiveGDPC, you can override these things. Basically, there's a number of conventions that it expects, naming conventions. So, for example, if you have a table called people, and you have your entity called person, it will map automatically. Actually, it does even that kind of a, you know, people, person, geese, goose. So, if you follow conventions, you don't need configuration. If you don't follow conventions, then you need to put some annotation. I'm talking about one-to-one mapping versus one-to-many. It does not support one-to-one mapping. It supports one-to-many and many-to-many, as well as polymorphic associations.
Mike Hall Interviewer, UGtastic
What kind of composition? What kind of composition?
Guest Guest
Like, you have an object, and that object has two children. Like, object A has object B and object C. And you put them in two different tables. Yeah, no problem.
Mike Hall Interviewer, UGtastic
Right. Right.
Guest Guest
That object has two children. That object A has object B and object C. And you put them in two different tables. Yeah, no problem. And then, how does it know that there could be only one object C in object A, and one object B in object A. And you put them in two different tables. Yeah, no problem. And then, how does it know that there could be only one object C in object A, and one object B in object A. And you put them in two different tables. Yeah, no problem. And then, how does it know that there could be only one object C in object A, and one object C in object A?
Mike Hall Interviewer, UGtastic
Why not C in object A?
Guest Guest
Because it finds, let's say, you have, let's say, a person, and then you have an address.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
Yes. Let's say, you have addresses table. We'll get to it.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
But, you know, if we're running ahead, the addresses table will be expected to have a person ID column in it. And if it finds it, it automatically sets the relationship between a person and address. And basically, it says, this person has many addresses. Yes. So, this table, people can have many types of relationships with other tables. Yeah, but that doesn't mean that the person can . Yes. That's not always true. Well, maybe when you get to .
Mike Hall Interviewer, UGtastic
Yeah. You're talking about one-to-one relationship? Yeah.
Guest Guest
It does not support one-to-one relationship, because I can't really fathom how it's represented in the database. All right. So, it should be very easy to work with. Remove code.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
No configuration. Just conventions. Conventions are overritable in code. Not in property files or XML. You do not need to learn another language. No HQL or any finicky thing. If you know Java and you know SQL, you can use ActiveGVC. And you will have to write very, very little about SQL. A quote must be lightweight and intuitive. You should read like English. There's a lot of English-like phrases that you write in ActiveGVC using so-called fluid interfaces. When you do something like, you do something, something, something, something. No sessions. Because ActiveGVC does not require a third-party object to operate on models, I'm going to start calling them models from now on.
Mike Hall Interviewer, UGtastic
Think of an MVC, okay?
Guest Guest
A model is your data. So what in, in Hibernate is called an entity, in ActiveGVC is called a model. Since models operate on self, there is no need for a third-party object and there is no session.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
You just call methods on the model itself and you're done. And models are, you know, you don't have to attach them to attach them. You have no persistent manager, again, no third-party object. And no classes on the side of one model. Basically, I collapse entire architecture from DAO, DTO, and entity into one class, model.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
You will see that. It's very, very easy and simple. Models are lightweight and they have no transient fields. Basically, you can take a model, you can serialize, you can deserialize it back and save it again if you want. It's, it's, it's, it's, it's going to be the same like, no proxy. I invented the new term.
Mike Hall Interviewer, UGtastic
What you write is what you get, okay?
Guest Guest
Well, in some other frameworks, sometimes you write one thing, but then you say, hey, session, get me this thing. And you think you get that thing, but it actually was a subclass. Okay, no setters and gathers. Okay, no setters and gathers. Well, that's what I thought back then, but now I'm kind of in between. Basically, you can have your setters and gathers. But certainly no DAOs and DTO.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Active JDBC is there. If, let's say, try to get something or put something in the database and we have exception coming from JDBC driver. So, the record is something. You see the stack trace. The stack trace is usually four or five minutes. So, it tells you the depth of the frame. So, fast. I have a simple test that stores 50,000 records in MySQL database and reads them all at once. One on Active JDBC, one on Hibernate. Active JDBC is about 40% faster. And Active JDBC is about 40% slower than JDBC, which tells you that Hibernate is about four times slower than JDBC. It also has caching implemented. And then when I did the slide, it was OScash, right now it's OScash and EHcash. All right. Size is about 10.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
It requires to get primary keys exactly the same way as Active Record. Basically, you have auto-incremented integer field that's been implemented as you enter your records. So, writing a model is pretty simple. You write it like this. Public last person extends model. This will automatically map to a people team.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
And, as you can see, the class is empty. Maps to people. No necessary details about this table from David.
Mike Hall Interviewer, UGtastic
Who knows?
Guest Guest
Immediately ready for corrupt operations.
Mike Hall Interviewer, UGtastic
So, what kind of operations?
Guest Guest
As you can see, I didn't write anything and I have nothing in it. But, I can start writing code like this. Person dot where, what's name equal John. And, again, list of people.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
And, then I'll just iterate through this. So, this should be pretty easy.
Mike Hall Interviewer, UGtastic
Any questions about this?
Guest Guest
So, when I show people this and then that, they actually don't ask me to write code and show them how this works. They will make this. We'll actually write a simple product location using FWGBC and active web in this presentation.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
All right. So, you can select those associations. For example, if I have another model, address extends model. And, obviously, fable addresses has a column person ID. As you can see, there's also inflection. The point in key is not people ID. It's person ID. It's all done right. Then, you can say a person find first and then provide a specific value. Basically, find first, runs the scale but limits the results to one and only returns to one. But, the point is this. Once you get your person, you can say a person get bold and pass what association you're actually interested in. A person can have many addresses. A person can have many books. A person may have many other things such as articles, whatever.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
So, the interesting thing is that active IDC supports three types of associations. One-to-many, many-to-many, and polymorphic. Quite similar to active record in Rails. And, the APIs to get all these things are identical. So, even if I have, let's say, a doctor-patient, with doctor-patients table in between, where a doctor treats many patients and a patient visits many doctors. It would still be saying, "Doctor, get all patients," or vice versa. Basically, this is, in my opinion, a lot more bo-ho, because I don't really care how the thing is done. Well, I care to a certain extent, but once I'm working on the level of my models, I'm thinking about my objects and not about records. Here's an example of synaptic fluent interfaces. A person where H is greater than 21, limit 4, offset 20, order by H is the same. So, the where method returns a special object called lazy list, which has all this stuff. And, each one of these methods returns that same lazy list. So, that means, as many times as you call and you configure, you further filter your query, it simply configures that lazy list. And that lazy list, which is also implementation of the list interface, Java util list, doesn't actually go through database. You're just configuring. That's until you start iterating through that list. When you start iterating through the list, then it goes through the database. So, in a sense, it's lazy in that sense. Not in a . All right.
Mike Hall Interviewer, UGtastic
So, you'd say, so what, I can write this query?
Guest Guest
Yes. Go ahead. Do it for Oracle, for instance. Good luck.
Mike Hall Interviewer, UGtastic
Okay. Do it for, what's it called?
Guest Guest
SQL server.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Every one is different. MySQL is one, you know, basically, we support about five or six databases. All major databases supported. MySQL, PostgreSQL, Oracle, H2. MS SQL, or something else. SQL server. SQL server, yes. But, it's all recorded on the website implementation. One way or the other, you have one API to upgrade.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
The thing that I was mentioning before is that you have to write a little bit of snippets of SQL there.
Mike Hall Interviewer, UGtastic
Okay. Okay.
Guest Guest
This is actual SQL. This is the part of SQL which people usually write after a where clause. That's why it says, person, where, age, greater than 21.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
If you just, if I just read this expression, and you didn't know I was reading code, you would've thought, I'm talking. All right. This is just standard language. That's the goal. Well, if you just need to create a new data, my person class doesn't have anything. But, it inherits the model.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
That's why I have a whole bunch of methods that I can use. And, so, I'm using, basically, these are setters. These are dynamic setters. And, dynamic setters, basically, it says, first parameter is the name, the column. And, the second one is the value. This is really not the name, the column. It's the name of it. And, think of active GDC as a hash map on steroids with lots and lots of semantic knowledge about the data. All right. There are so many ways to create new data. You can create data like this because the set method returns this. You can create it like this. Create hit, first name, basically, name, value, name, value, name, value. The created method, of course, expects even number, even number of arguments. The first, third, and, basically, every odd argument is the name of an entity.
Mike Hall Interviewer, UGtastic
Can it take extreme form? What?
Guest Guest
It doesn't take any mistakes. Oh, it takes any. Any, any object. Whatever object that will be accepted by your driver and the database, this parameter is safe. This parameter is up. It's up to you. It's up to you. But then you can write your own setter and getter and wrap this thing around it. By the way, there are setters and getters. These are dynamic setters and getters. These are generic setters and getters. But there are setters and getters that actually do conversion of a value into a specific type. Let's say there's a get string, get timestamp, get integer, get float, and so forth. But those conversions are actually pretty advanced. First, it tries to find out if it's that type. Then it tries to find out if it's a superclass. Let's say for dates and timestamps and stuff. If that doesn't happen, then it converts that to a string and tries to parse that into a string. If that doesn't happen, then it throws in a circumstance. I can't do it. But it's also transparent to things like clogs. You can say get string and pass a name of a column, which actually is a club. You're going to get a fully read club into your string. Just be careful. If your club is large, you're going to run out of there. Validations. Validations are declarative. Basically, this is in the style of active record, which is really cool. I think that the slide is missing. So the idea here is that I'm saying that this thing needs a validating presence of first name and last name. Meaning this model will be throwing an exception if you try to save it into a database, but when either one of this is missing and you're going to get error messages. Alright. Validation, you know, a little bit more validation. This is a more advanced set of validation rules. Basically, we're saying that the total shouldn't be just present. I want this to be a number. But I also allow it to be null. But if it's a number, I want it to be greater than zero and less than 100. Maybe it's a percentage or something. And I only want it to be an integer. Oh, by the way, here I'm also operating a default message. Now, the value that it put into message, basically every validation message, every validation method accepts, also has this message method attached to it that you can use to pass in either a derivative message or a key from a resource model. So the whole thing is actually internationalized and the validation framework is just so advanced here. It's dynamic. You can carry it on messages within, on values within messages and so forth. It's actually pretty, pretty good. Part of it was dynamic. All right.
Mike Hall Interviewer, UGtastic
So, anybody here familiar with save and, with Ruby and Rails? Yeah?
Guest Guest
Well, okay. You probably know the difference between save and save bang. So, the save basically returns boolean and says, I was saved or I wasn't saved. It's very convenient for a web project where you say, save this thing, or you say, if not saved, show an error page. If saved, just go the normal way.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
Save it on the other hand. If something, if there's a problem, let's say validation problem, it'll throw an exception. All right. Example of one-to-many relationship. Say I have a user extends model and I have address extends model. And all I have to do is that the addresses table needs to have a column user. After that, I can start writing my code and the two. So, by the way, if you try to do something like, if you try to say a user dot get all books dot class, and there's no relationship to books, then you're going to get an exception saying, I don't have association to that thing. However, I do have these associations.
Mike Hall Interviewer, UGtastic
Is that a runtime exception?
Guest Guest
Yes. It's an exception.
Mike Hall Interviewer, UGtastic
What do you mean? It's runtime? Do you have to catch it or not?
Guest Guest
Oh, you don't have to catch it. Nothing needs to be caught.
Mike Hall Interviewer, UGtastic
You mean if it's a checked exception or runtime exception?
Guest Guest
Yes. It's a runtime exception.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Many to many. Same. I think I mentioned this before. Let's say you have a table of doctors, then you have a table of patients. Then you have a model of doctors, then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Then you have a model of patients. Which will have a model of patients. So, and by the way, this model of patients table could be called a patient of patients. It doesn't really matter. The framework basically says, okay, for this state, I'm going to find all possible variations of all relationships that I'm looking for. And if it finds it, it will just configure it. And then I can do things like that. Patient. getAll, doctor, or the mirror of that, you know, doctor. The getAll method returns all results, all related records. But the get method has multiple parameters. So you can filter down what exactly you want. All right. So, this is kind of a summary of adding and removing API across multiple types of relationships. Let's say one too many, many too many polymorphic. It's the same. Removing results are the same. And so you can see that the framework is very symmetrical in a sense. Once you learn the API, if you expect it should be like that, it probably will be like that. The same couple words is polymorphic. Polymorphic association is when you have, let's say, in one too many relationships, you have a parent and you have children. Let's say, let's say you have an article and you have tags.
Mike Hall Interviewer, UGtastic
Articles and tags, right?
Guest Guest
The problem is, let's say, I want to tag articles, but I also want to tag products.
Mike Hall Interviewer, UGtastic
Now, my tags, well, do I create another different table for product tags? Okay?
Guest Guest
So, the polymorphic association allows to use the same table, but to have children there that belongs to parents of different types.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
So, which is a pretty good, pretty typical scenario. Active record supports it right under the box and so does after GDC. I don't do it .
Mike Hall Interviewer, UGtastic
Okay. So, when you process, you say, here's my IDE and data, and then how is my type?
Guest Guest
I might have a slide on that.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
They also have originality fields. There are three fields that here, obviously, is the primary key, but there are also two more. Create that and update that. If your table has them, ActiveJVC will use them. And when the new table is, new record is inserted, they both have the same value, but then if you read that value and then change something in your own model and then save it again, update it will have the last updated value. It's really convenient. All right. Caching. It's pretty simple. We put a cache mutation. We're done.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Of course, OS cache. Both OS cache and EH cache support clustering and they use a variety of techniques. They use J groups. They use messaging. So you can configure clustering, configure caching in closed cluster. It's not something that's trivial, but it's also not part of the fact of GDC. It's really part of the integrated framework. And that's not something that I have to run a daemon for service. That's-- No, no, no, no. This is called near cache. That means if I have multiple nodes in my cluster, then each node will have its own private cache. However, whenever there is a destructive operation that goes through active GDC, the cache for that table and its related tables is blown away. And that event is propagated to other nodes in the cluster and they blow away those caches as well. There's no daemon. Lifecycle callbacks, you can implement these methods and do whatever you want. They're going to be called from framework. This is a callback example. User extends model. Before save, we say that the password has to be encrypted. So we encrypt the thing before we actually say it's pretty convenient. So framework actually allows you to put code in the right places. Now, this is pretty interesting. The include is a very powerful method. The notion of lazy eager is completely different between active GDC and Hibernate. Hibernate was designed during the times of client-server programming in 1998, 1999, the first version in 1999. Today, 90% of stuff is done for the good. So that type of lazy eager is not needed anymore and I think it just complicates that actually. Active GDC is just plainly lazy. In fact, it's more lazy than happening because once you get, let's say, a list of things that are related, let's say get the user get all addresses. You call that method again, you go to the address again, unless you're in a cache. Now, here, I can say user find all order by ID.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
I find my users. That's fine. But I can also do that include addresses.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
Let's say if I wanted to display on my webpage users and their addresses.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
Let's say many addresses per user. I could do a trivial, you know, path. I could go a trivial path where I get all my users and for each user I get all addresses. That means I'm going to do N plus one queries for that. I'm going to get all users and then for each user, one more query for addresses. On the other hand, if I do include addresses. Include address dot. Pretty much you're telling the framework to do two queries regardless how many objects there are.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
First, get all users and then get all addresses of those users. At which point, when you start doing user dot, get addresses, you're going to get them.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
The difference is unloading. By the way, they include tags and var arcs. So you can say address dot. You can also include parent type relationship and child type relationship in one call. In that case, you're going to have three for square place. One for each name. Logging. Logging is also quite advanced. If you say -dactivate dot log. If you just say log, okay, it's going to be logging. Or you can provide your regular expression. Basically, you filter out what you want to see in your log. The other thing that's interesting is that there's API in the framework that you can call to pass a new expression to change logging on the file. Ta-da! Well, there's a lot more about ActiveGVC. I just don't want to - I want to jam everything within an hour.
Mike Hall Interviewer, UGtastic
So any questions about ActiveGVC?
Guest Guest
I hope it seems magical. Well, that's good. But if you peek under the hoodie, you'll see that there's no idea. Go ahead.
Mike Hall Interviewer, UGtastic
What license is it?
Guest Guest
It's a patch of two. Three. I'm just trying to frame the question I have in here. And kind of real life problem. Let me get back to that. All right. All right. That's all right. No problem. So, guys.
Mike Hall Interviewer, UGtastic
Any questions? Or a question? How long did this take you to get?
Guest Guest
It's an ongoing - well, basically, there was one really, really hard problem to solve. Which is a person dot mirror. Since studied methods are not in Java. It has a post-compile process for instrumentation. So it took me a while to figure that out. Yes. So a lot of people kind of dislike it, but once you move it in your day-to-day process, like, I don't notice it. You click on the button and everything just happens. So I started in prototyping that in September of '09. I had a working prototype in October. And by November, I had most of the implementation done. And January 1st, it was more of the right in production powering website for insurance. So, since then, I've added more features. But I would say that over the past maybe a year, a year and a half, I'm not adding any more features. I'm just fixing bugs here and there. And then I'm accepting contributions from community. So, for instance, the original implementation had only support for three databases. Postgre, MySQL, and Oracle. And then all others were added by the people. Part of the validation framework was owned by people in Brazil. Then H2 support was added by some back from Japan. So there's a number of people. But I would say that API is pretty much similar.
Mike Hall Interviewer, UGtastic
And the documentation, were you able to get on the web?
Guest Guest
Yeah, I wasn't able to get on the web. But you can Google Active JVC. The docs are all there. There's also Google Groups support forum where you can ask questions. And that people, me and a bunch of other people, will throw out answers. It's pretty quick to answer questions. Usually, same day. And I'm actually, I'm with the same team as Igor. And I've actually had to use this on days where Igor was not there. And I was able to figure it out. And I'm not a Java guy. So it's, and the docs are good. I'll give you credit for that. Most open source projects don't have that much time. Yeah, just looking at it on, off of the GitHub website. I looked at it briefly last night. That seemed very straightforward.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Thanks. That's the magical.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
I'm just not good. You know, my neighbor is not that good. So if I develop a feature and I don't recommend it, I wouldn't remember how to use it. I can't remember. Some of the really complicated SQL. See, I mostly develop active GDC because I'm really bad at SQL. Well, it's one of many reasons. So some of the SQL was provided by any people. So I used that SQL as a template, basically filled in my dynamic values. That's why I said, I need to do this and this. So maybe it's using some other tools. I remember that the most complicated SQL is for Oracle to support limit accept and something else. And I didn't write it. And I didn't write it. But the developer and my team actually was good at SQL. So I did that thing. And I tested it against a table with millions and millions of records and it was good. Basically, the response was flat. Speed was amazing. No problem. No problem. But then somebody in the community said that specifically it could be optimized. You actually have to be on Oracle to be added to that. So sorry, I can't .
Mike Hall Interviewer, UGtastic
Can you pass in any hints to SQL for transactions?
Guest Guest
With SQL server I can say, just basically do a fast forward read only cursor. I can pass that hint along with a query.
Mike Hall Interviewer, UGtastic
Can I do anything like that?
Guest Guest
No, you can't do that. See, we would have to go back to my original slide where I say, provides 80% of the typical functionality and the 20 other percent. On the one hand, I don't feel it is ORM. On the other hand, I don't feel it is the right thing to provide my framework. Because if you have to have that find, tune, you know, access to a specific function of your database, God forbid to depend on the framework. But a lot of frameworks do provide a way to send arbitrary SQL and then return back like an array. Oh yeah, yeah. ActiveNMC can do that as well.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
So I could, if I had to do a specialized query, I could. You can freehand your SQL. You can just say person dot find by SQL and write your SQL. As long as it conforms to a person. As long as the result will bring the cons for this model.
Mike Hall Interviewer, UGtastic
Okay? Okay.
Guest Guest
If not, there is a lower level API class called base. Base, you say base dot find and just find, provide whatever SQL you want. From there, you get a list of maps.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
And by the way, the find method can also get a record listener. It can provide the listener. Because, you know, the first implementation returns the entire results set in memory. You get the list, which is either. The other one is not lazy, but it's like a cursor. It's scrolling ahead and you get one record of the time, but you get in the form of a Java hash map. Java map. Java map. Where keys are columns from that table, and values are values from that problem. So it's kind of a convenient thing. But the nice thing about it is like, in one line of code, you can write a quote unquote loop that will parse millions of records from your table without having to spend anything.
Mike Hall Interviewer, UGtastic
Does that answer?
Guest Guest
Yeah, yeah. It also doesn't have support for stored procedures. Actually, that was the one that I was trying to inform on my list. Because stored procedures are not ORM.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
I know, but that's something, like, they're really popular in SQL Server. So I'm just going to say, is there a way to, like, I know in length of SQL and things like that, I can define mappings to stored procedures. But they were a special case, so. Yes, but the thing is that you can write that stored procedure management code inside the model and wrap it as a service and off you go. In other words, the model itself is a good place to put that. Or I could just do the base and then exec. Yeah, within that model you probably would use the bases. No. ActiveJVC uses the so-called dry principle. Meaning, if something is provided by an underlying system, it will not provide it. And transaction, you know, square will fall into that kind of way. It has a couple methods to start and start and stop transaction to roll back. But those are convenience methods. Basically, you can say, start transaction, you do a lot of activeJVC code. Then you save.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
But those are the same normal calls. They're just a little bit more convenient.
Mike Hall Interviewer, UGtastic
But whose model is it? Model model?
Guest Guest
It's not model. There's a class called DB. Classical DB or base. Basically, activeJVC actually also provides ability to map at runtime models that are mapped to different schemas, even to different databases. Let's say an example where within one system I'm using models. One set of models belong to MySQL schema and the other to Oracle. You can do that. So for something like that, you obviously need to have two database connections. One to one database, one to another. In that case, you use a class called DB. If you only need one, then you use base. Basically, the base and DB are similar. There's a page that describes you what they're for. The point is the base class will have methods to start this connection. But underneath, you'll see that it's doing nothing other than connection set of a commit false or a commit or a connection . So basically, you're in full control of what's happening. If you're using standard connection that you're working within JDB container, then you're under the same principles as any other code. Imagine that you rip out all the active JDBC code and plug in JDBC code. The same exact reason. And so, if you're writing your active JDBC code within, let's say, in the branch of a beam, then you automatically have connections. I'm kind of interested in -- I'm not a Rails developer. Rails is new to me. I just started dabbling in what's been around a while.
Mike Hall Interviewer, UGtastic
But does Rails provide transactions or methods for doing transactions and access things towards procedures and so forth?
Guest Guest
I haven't had to do it. I mean, just comparing this to -- excuse me. I haven't had to do it. It's really not in the culture for us to use -- No. That's where you start. Five years.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
The last time I had used a certain procedure was when I was doing that.
Mike Hall Interviewer, UGtastic
Yeah. Okay.
Guest Guest
Yeah, it didn't seem like it would -- Well, as far as transactions -- -- mesh well with it. But as far as transactions, yeah, they do separate transactions. You can't do transactions. Yes. I know that doesn't -- I'm just trying to -- Yeah. For instance, in active web and in Rails, whenever you run a test, each test is run in the context of a transaction, which is rolled back on the other test.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Which leaves your database in a good state for the next test. And active web does the same thing.
Mike Hall Interviewer, UGtastic
Right. Is it all written Java? Active web?
Guest Guest
Active web. Right there. Active JVC.
Mike Hall Interviewer, UGtastic
Yeah. Yeah.
Guest Guest
It's a Java file.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
100K in size. No native web. No native web. No native web. No native web. No native web. No native web.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
I lost my C++ transaction. No native web. So, okay. That was good because transactions was one of the things that I was talking. So if I understood that right, there's a mechanism there that will allow you to tap into that commit rollback piece in there.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
So that gives us that piece, which of course would be, you know, like you said, dependent on your application. That's good.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
I'll tell you what's confusing because I'm stuck in the grabbing entity and then model. And then once you've got the entity, you pass the value, a value object, which is just a pojo that you don't touch.
Mike Hall Interviewer, UGtastic
Right.
Guest Guest
And then that's kind of a read only kind of thing.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
And that's not what we're dealing with here. And that's fine. So that's part of my confusion. So, but that also gets other confusion on my part because a lot of times we will have getters and setters that act on the value objects, which will do various things, which will then translate into something else that could get put down into the database. This looks like right here, we're a little closer to the database. Yes. In other words, if I set this. Close to the middle.
Mike Hall Interviewer, UGtastic
Right. Exactly. Exactly. Yeah. Yeah. Okay.
Guest Guest
The other thing is the, so when you're doing a getter or anything, you're actually providing the column name or the attribute name, right? That's generally how you.
Mike Hall Interviewer, UGtastic
Yeah. Yeah.
Guest Guest
So. As if it were a hash name.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
But it probably got backed up by that. But the name corresponds to the name of the column.
Mike Hall Interviewer, UGtastic
Right. Exactly.
Guest Guest
Because internally, well, it doesn't say a hash name. See, that's the other thing too. Well, I'm just going back from mindset, where everything is being driven by a database that has been constructed. And then the other way is, you know, we have a hibernate and just have that generated. I think your approach is really a better approach to take because it allows you to consider what you're building and, you know.
Mike Hall Interviewer, UGtastic
Exactly.
Guest Guest
In ActiveGDPC. ActiveGDPC, unlike Hibernate, will not generate tables. It will read them and configure itself. That means the tables have to exist. That means you are forced to write an SQL. That means you are forced to think.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Which is another thing. Which violates the leasing.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
The, um. Well, there's a lot of violations here. People are like, hey, no property files. Or no setters and gathers. Or no, the last guy hit a belt, oh, no DAOs and, oh, hit a belt to the where method because it was static. Like, we're not allowed to write static methods.
Mike Hall Interviewer, UGtastic
Why?
Guest Guest
So, uh, it's not, uh, it's not conforming to kind of quote-unquote standard, uh, um, Java practice, which I personally find pitiful, unfortunately. Java developers are stuck in, like, ten, you know, in the style of code that was quote-unquote popularized, uh, ten years ago. And they still go with it, uh, without kind of looking outside. And I was, I was a sinner, just like that. Uh, until I learned Ruby and Rails and then Ruby and Rails, uh, and then you, you start to realize that, you know, all that garbage code that I've been writing is actually garbage code.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Like, you never have to worry about getting to move to the next record.
Mike Hall Interviewer, UGtastic
Exactly. Exactly.
Guest Guest
Uh, you have some interesting logging, um, information that you show.
Mike Hall Interviewer, UGtastic
Are you gonna show us some code? Logging?
Guest Guest
The one thing I wanted to ask is that, I can't remember, is there, like, a way just to log the, um, no, I meant, like, are you gonna, like, show the output?
Mike Hall Interviewer, UGtastic
Yeah. Is there a way to log just, um, queries? Yeah.
Guest Guest
I, I always, like, I always like to see action record.
Mike Hall Interviewer, UGtastic
What is the action? What I just did, what is the sequence?
Guest Guest
Yeah, yeah. What we have to do is provide a regular expression here in which...
Mike Hall Interviewer, UGtastic
But that'll just log?
Guest Guest
Selected message.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Selected text. Basically, it says, every time, everything that will be logged can be filtered by this regular expression.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
So, you, you can knock yourself out and write whatever complicated expression just catch, you know, let's say, I want to catch select and insert, but not updates of these.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Cool. And prepared, it looks like it supports prepared statements as well. Yes, it does. It actually caches prepared statements on the general, yes. That's not it. It has a little cache on the inside. That gives us some safety for injection. Yes. All right. All clear with Dr.
Mike Hall Interviewer, UGtastic
GBC?
Guest Guest
Actually, people who... I've interviewed people using this thing after months of day in and day out. And, you know, and the reaction was like, there's nothing to talk about. Like, when you have comfortable shoes, you don't think about shoes. You just focus on where you're going.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
And if you have uncomfortable shoes, you constantly think about those shoes. So, that was a relief for me to hear that. All right. What I'd like to do now is I'd like to show you a little bit of active GBC code, which is also part of my example part, but it's probably going to be pretty cool to see. The example that I'm going to show you is an example from active web. I'd like to show you that example first, even though you don't know anything about active web. But this little example has a snippet of active GBC. And I just want to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. I'm going to show you what it looks like in real life. Basically, I'm creating two brand new databases. I'm going to show you what it looks like in real life. I have a script here to create a so-called migration.
Mike Hall Interviewer, UGtastic
Are you guys familiar with the notion of migrations? Okay.
Guest Guest
All right. Script. New migration.
Mike Hall Interviewer, UGtastic
What table do I want to create?
Guest Guest
Articles. Let's say I want to create an article. Create articles. Type all.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Articles.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Articles.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Articles. All right. This little script will create me an empty file. Once I have this empty file, this is Java. 100% Java. This is Java. 100% Java. The migrations are part of active web project, which you haven't seen yet, but I'm using active web with migrations to show how to operate on active jvc. It isn't shell script.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
But that shell script is a Maven command. I will show you.
Mike Hall Interviewer, UGtastic
Yeah. Yeah. Yeah.
Guest Guest
This is the content. This is the content of my shell script. I'm using a database migration Maven plugin. Sorry. I should probably move. Here. All right. So, once I have this file, the file is empty, as you can see here. The file has this weird name where it prepended a timestamp to create article stable text that I provide. I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. And then I'll just go ahead and create the table. So once I have this file, the file is empty. So as you can see the file has this weird name where it prepended a timestamp to create article-stable text that I provide. I'll just go ahead and create the table. I have code conveniently prepared for me by someone. Here. And then I'm running a second script. MigrateDB, which is a different goal on the same plugin, which is going to run two migrations for me. One against the simple development. The other one against the simple testing. Both of these are configured in like plugin number five. No big deal. But the process is exactly the same or similar to Ruby and Rails. You create your migration, then you run migration script. That migration goes into a database. So at this point, I can say -- I can -- You saw that. I just dropped my databases. And then I create a database and I run my migration. I have articles and I have two migrations.
Mike Hall Interviewer, UGtastic
Okay. Great.
Guest Guest
At which point, I'll go and create my model. In models, create a new class. New Java class. Articles. Extensive model. The next step would be to -- well, let's say I want in this model, I want -- how many people here are familiar with R-SPAN?
Mike Hall Interviewer, UGtastic
Two? Two? Is that a little bit? Yeah. Okay. Okay.
Guest Guest
This is a test. I'm writing a test immediately. My model doesn't have anything, but I'm writing a test. This test is nothing more than a JUnit test. But it's written in a style that's very different and important to Java. Shoot. Shoot. Shoot. Shoot. Wait a minute. Yes. As you can see, my method is not called test something. It says shoot something. Shoot something.
Mike Hall Interviewer, UGtastic
Okay. Okay. Okay.
Guest Guest
This is a test. I'm writing a test immediately. My model doesn't have anything, but I'm writing a test. to John. As you can see, my method is not called test something. It says should something. Meaning, I should start working with validations. Article A equals new article. And here I will say for the article teach the article shoot the valid. All right. Let's say you don't know what's happening here. But you can at least read this and understand what this is.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
Because it's kind of like English. If you just read a sentence, the article should not be valid.
Mike Hall Interviewer, UGtastic
Why should it not be valid?
Guest Guest
Because probably it's missing something.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
Like content author or something. So let's run this test.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
And the test says method is valid, should be returned false, but returned true. What happened here, a little bit of jspec magic. We actually have three frameworks. ActiveJVC, ActiveWeb, and jspec. And what you see over here is jspec. Basically, jspec is a set of assertions that are written as expectations instead of assertions.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
I could say, um, something like, assert, um, true.
Mike Hall Interviewer, UGtastic
Okay. Okay.
Guest Guest
Assert true. Article is valid. I could write it like this. Actually, it serves exactly the same purpose. However, uh, this is, uh, harder to read and counterintuitive. And also leads to poor TDD or no TDD, where this is a specification of my, uh, or kind of documentation of my specification. My, my, my VA said that the article should, uh, have these columns filled. Otherwise it's no article. So I'm documenting in here the article should not be valid. Um, so, but it's failing because article is valid.
Mike Hall Interviewer, UGtastic
Why is it valid?
Guest Guest
Because it has no regulations. I'll just say static, um, validate, um, present, so, um, these things. Alright. Now if I run the test, the article is not going to be valid because I'm, I'm asking that these things should be present, but they're not present. Therefore, the test that says the article should not be valid is correct. So all I have to do is, uh, do things like this. So, um, set, um, set, um. Yes. The valid, basically, if it looks for, it uses JavaBeans conventions, uh, to look for methods, uh, let's start with is valid, has valid, you know, things like that. If it finds one, it executes it, and then uses that for relating, uh, the expression. Um, so there's a little bit of magic there. But not much. Uh, author, let's say, uh, uh, author, let's say. Now I'm going to, if you do this, it's still not valid, but now, I'm going to do this. I can say, after I sent all these things, the article should be done. And here it is. So this is the style of development we have with ActiveGVC. As you can see, my article class has still very little code.
Mike Hall Interviewer, UGtastic
Any questions about this?
Guest Guest
I really would like to proceed to ActiveWeb because we're seriously running out of time. Unless you guys give me another.
Mike Hall Interviewer, UGtastic
Here? Yeah? Yeah. Okay. Sure.
Guest Guest
All right.
Mike Hall Interviewer, UGtastic
So, what do you guys think?
Guest Guest
Now that you've kind of touched, there's a lot more, of course, the framework because it's been developed for more than two years. You've been in production, powered in insurance companies, probably, you know, a few public websites. But you haven't developed something like that, you know, in style of ActiveRecord because it didn't exist in Java.
Mike Hall Interviewer, UGtastic
So, what's your first reaction?
Guest Guest
There's a lot that I like. I like the fact that it's sort of a declarative type of thing. For example, your validations. There's not a lot of fluff or things that you need to do to make the plumbing work, you know, to be able to do that. The only thing that jumps out at me, and it's just really a process problem for a user, would be, they've got to know what the field means, you know, they have to know that there's an author. So, I think people that are just like, you know, that is true, like our lazy people that I have. That's why you can encapsulate them in others and others like that, that actually have names and actual types.
Mike Hall Interviewer, UGtastic
Set content takes a statement, right?
Guest Guest
Of course, in my simple example, every column here is text.
Mike Hall Interviewer, UGtastic
Yeah. Now, I'm sorry, was that something, there's no auto-way?
Guest Guest
There is no generation.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
But you do have the automated generated docs.
Mike Hall Interviewer, UGtastic
The doc? Yeah. How are you generating those docs?
Guest Guest
Copy-paste. From the SQL. Into-- Basically, this is what I do sometimes. I know what Mike is talking about.
Mike Hall Interviewer, UGtastic
Well, that isn't automatically generated?
Guest Guest
I thought it was. No. No, it wasn't. I do this. But you should be able to, at some point, be able to get to the underlying.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
But it's actually not that trivial, as you might-- I'm not saying that's a bad thing at all, because there is a certain-- Now that I have this thing in here, I can go to another place, you know, click on my-- I can see my article and see what it has. I mean, something like mapping between Java code and a database, even though it seems so lightweight and easy in active GPC, still, you have to pay attention to it.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Because I could see it. Well, even like, you know, you were like, ah, we're in the heat of the moment. There's typos that we put in.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
And you won't really see them until you run the test that you wrote. That's kind of the-- it's just-- code generation is not a trivial thing.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Number one, the code generator might not be part of the framework, so it has to have-- be able to-- ability to go to the database and retrieve all that metadata, generate all that code, and then find source code.
Mike Hall Interviewer, UGtastic
And where can source code do you stick it in?
Guest Guest
You have to assign, like, a region inside your class where code that is generated is-- Yeah. --and then if somebody messes, like, header and footer, then they're generated-- And this is kind of strappling the style of, like, you know, Ruby and Python, where you don't get that-- you don't generally have that kind of tooling where it's going to give you intelligence and auto-completion.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
And that's why we lean so heavily on tests. Which is always a good thing.
Mike Hall Interviewer, UGtastic
Yeah. Yeah.
Guest Guest
Even if you've got auto-completion.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Absolutely. But let's say, I know that some Rails developers write models in this style. They actually have setters in the others in this style. But most people that have those really wish they didn't have to do that.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
See, really, what we want is to come out like-- No, that's true. --unless we need to actually have a getter or a setter that operates differently than just . I don't think that's even really easily supported in Java. I know that in order to get that in . NET with the . NET 4. 0 and the dynamic and having IntelliSense on the dynamic keyword. And I don't even think everything is-- I don't think it picks up. It's been a while. I only started . NET 4. 0 when it first came out. And I was playing around with the dynamic keyword so you could have things like that where it's like-- It does inflection and the studio will go and figure out what you're trying to talk to, looking at config files and stuff like that.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
It took a lot. And it took changing the framework itself to-- Yeah, but there's no really good way to doing it. And then you need to either do the reflection or instrument . Yeah, but then you can't compile against it. In Java, you can add anything at runtime. That's the other, yeah.
Mike Hall Interviewer, UGtastic
But how do you compile against it?
Guest Guest
But Ruby, Python being interpreted languages, there's no compiler. No compiler, no problem. So that's what I mean. We come around to the-- this isn't really a bad way to do it at all. Not really. No. I mean, you have to-- today, you know, I'm contemplating whether to write a code generator or not. But today, if you want getters and setters, you have to plug it like this. So basically, you need to wrap the dynamic setters and getters with your own static. Static, in a sense, static . I don't know anything about Hibernate or anything like that. I've not used those tools. You would write this in Hibernate one by the way. That's what I was going to ask. Yeah, because in Hibernate, you would do-- this would be like a pojo, a value. It's the first thing you'd do.
Mike Hall Interviewer, UGtastic
Right.
Guest Guest
You'd lay it out, you'd put your getters and setters, and then pass them in it. So you do-- but at least with this, you get some dynamic, you know, the string names.
Mike Hall Interviewer, UGtastic
With this, you have an option of having them or not?
Guest Guest
Or not, yeah.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Without having-- All right. Guys, I'd like to proceed to Active Web. So if ActiveGDPC is the standalone ORM that could be used in any generic Java project, then ActiveWeb is the rest of Ruby on Rails, which is a web framework for building web applications in Java. In a very fast dynamic way, very similar to Ruby on Rails. And it also has-- follows the same principle as ActiveGDPC. No-- no-- the convention exists. I mean, no conventions. No-- I mean, conventions, no configuration. Convention-based configuration. If you know conventions, most conventions are the same as Ruby on Rails. So people switching between, let's say, Ruby on Rails and ActiveWeb would feel right at home. But most people who are using ActiveGDPC are people who are kind of former Ruby developers forced back into Java and looking for alternatives to TaggerNet because they kept there. All right. So ActiveWeb. I was thinking, instead of running through slides, I was thinking maybe running a simple project and show you how things work. First, dynamically, and then we will build on that article example, basically build a product location for articles in this little program. All right. ActiveWeb is a Maven project. Anybody who's not familiar with Maven will have to learn Maven because you can't use ActiveWeb without Maven. It's all dependent. However, those who do know Maven feel right at home. Maven could be perceived by many people as the best things in sliced bread versus the worst people that came to Java. I tend to belong closer to the first camp. I think it's a great system once you master knowledge to use it.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Those familiar with Maven will feel right at home until they open the Java folder. Once they open the Java folder, they receive this app. Under app, there is a config package and there is a controller package. Controllers package. Now, you say, why app, not why not come, my company, my project, yada, yada, yada. Because I said so. Because it's app controllers, app config.
Mike Hall Interviewer, UGtastic
Why?
Guest Guest
Because people would be looking for the same thing everywhere. And the question is, why do you even need come company, come that company, that project, yada, yada.
Mike Hall Interviewer, UGtastic
Why do you need that?
Guest Guest
You need, originally, I mean, C++ didn't have namespaces. But then they figured out, okay, maybe Java needs namespaces because then you can have a class that has the same name in two different packages.
Mike Hall Interviewer, UGtastic
Great.
Guest Guest
That's it. Now, if you're building a common project and you're floating that project across your organization, I could see why that would be useful.
Mike Hall Interviewer, UGtastic
But a web application cannot be shared by another project, right?
Guest Guest
It's impossible because the controllers that make up this web application only belong here and nowhere else. Therefore, app controllers.
Mike Hall Interviewer, UGtastic
So, everybody's familiar with the notion of what a controller is? Okay.
Guest Guest
Those who are not, a controller in Active Web is the same as in Rails, same as in Spring MVC. Basically, it's a software component which takes an HTTP request and processes. That's it. All right. Once we open controllers, you see Books controller, Glitius controller, and Home controller. Now, I started my application. Active Web also runs on top of JD container. So, you have, in your palm, configured a JD container, and then you can start your application by running that plugin, Maven plugin. The great thing about Maven is just you have plugins just for a while in it. Once I access my application, localhost ADA, the Active Web Simple, that's the name of my build, I get this interesting page. So, immediately you see that it has simple, that it has on top some sort of a header. Underneath it has footer. And once I navigate from one page to another, header and footer don't change. It doesn't matter what's happening here right now, but header and footer don't change.
Mike Hall Interviewer, UGtastic
You've probably heard of site mesh or tiles in Java, right?
Guest Guest
For doing layouts, websites, header and footer, names and stuff. So, it's all built into Active Web. You don't have to build it. So, the whole idea of Active Web is that you have one framework. It does everything you need. It does logging. It does testing. It does layout. It does AJAX. It does an occlusive JavaScript. Everything you need is right there. Well, maybe not everything, but maybe, again, 80% of what you will need is there.
Mike Hall Interviewer, UGtastic
So, guess what?
Guest Guest
I'm going to type something here. Let's say, McHenry. All right, I get 404 Assertment Pound. Obviously, there's nothing in the application that has that. However, I get this interesting exception that says McHenry controller is missing. Ooh, cool.
Mike Hall Interviewer, UGtastic
Guess what?
Guest Guest
I'm going to go ahead and get that controller into my controller's package.
Mike Hall Interviewer, UGtastic
Is that missing the C key? Uh, you want?
Guest Guest
Yes. My camera. All right. My camera controller.
Mike Hall Interviewer, UGtastic
Got it now?
Guest Guest
I guess I'm also preparing.
Mike Hall Interviewer, UGtastic
How about this?
Guest Guest
Mc_Henry. Now, I have nicely, um, named the controller. That, uh, is easy to read for me.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
I'm going to copy that. And I'm going to create the controller with this name. So, it does, uh, interpolation of underscores and dashes into a camel case for Java. New Java clause. All right. Uh, refresh this page. It says, "McHenry controller is not a controller. It should extents. Work. Java-like. I can play back controller. " Of course, it doesn't. I forgot. Extents app controller. F5. Now, it says, "McHenry controller index action is missing.
Mike Hall Interviewer, UGtastic
" Right? Right?
Guest Guest
So, methods that are called directly from, um, um, from HTTP request. Are called actions. I refresh now. They get, uh, "McHenry controller is not a controller.
Mike Hall Interviewer, UGtastic
" Okay? Okay.
Guest Guest
I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to do that. And I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. And I'm going to do that. And then I'm going to do that. I'm going to do that. I'm going to do that. And then I'm going to do that. I'm going to do that. I'm going to do that. I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And then I'm going to do that. And I added a new class that didn't even exist at the time of the start. And then I added a method. Then I extended the class. And then I added a method.
Mike Hall Interviewer, UGtastic
So what's happening here?
Guest Guest
The framework automatically finds new code, compiles it on the fly, and links it dynamically into a running application without you having to come from the start and the start. Those who are building web applications, I hope, are relieved to find out that it's possible to do the job. In Ruby, of course, it's possible because Ruby doesn't compile anymore. It's an interpretive language. However, let's do something interesting here. Let's say we respond -- I wish I knew how to type. By the way, if I have gone that wouldn't compile, I'm going to get a compiler assumption.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
It tells me exactly what the problem is.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
All right. Depression there. And I get a little mechanic.
Mike Hall Interviewer, UGtastic
How about that?
Guest Guest
I have a perfectly working web application without almost having to lift a thing. No configuration. No configuration. And I have properly matched URLs to code.
Mike Hall Interviewer, UGtastic
What do you think of that?
Guest Guest
It's not that I want a pattern stronger. I'm just curious about the action. All right. Let's make it a web service. Let's make it a web service. Let's return something similar. All right.
Mike Hall Interviewer, UGtastic
Okay. Okay.
Guest Guest
Let's make it a web service. Let's return something similar. All right. So far so good. But in sources, we see that it's still.
Mike Hall Interviewer, UGtastic
Okay. Okay.
Guest Guest
So far so good. All right. All right. All right. All right. All right. All right. Let's make it a web service. Let's return something similar. All right. All right. So far so good. But in sources, we see that it's still a message for the long period. So far so good. By the way, this response thing is absolutely fantastic for building Ajax applications because you respond with JSON and you can see that it's still a message. So far so good. By the way, this response thing is absolutely fantastic for building Ajax applications because you respond with JSON and that's how it works. So far I'm going back to the same step where it says missing a template. Build it all and create that template. The templates are under web app web inf views. Here I'm going to have to create a new directory with the same name as the controller.
Mike Hall Interviewer, UGtastic
Correct?
Guest Guest
Yes. I would let you know if it wasn't. All right. Thanks. All right. Hi. I'm Mike. I'm Igor's spell checker. Yes. I see you're typing a template.
Mike Hall Interviewer, UGtastic
Do you need help with that?
Guest Guest
That would be awesome. All right. Now I have my page properly displayed in the layout. We'll touch in a second later, you know, with how the layouts work. And, now I have an entire application fall through. However, I'd like to make it a little bit more than name. Name equals . All right. In my controller, I have a little bit more than name equals . All right. Now I have my page properly displayed in the layout. We'll touch in a second later, you know, with how the layouts work. And, now I have an entire application fall through. However, I'd like to make it a little bit more than name equals . All right. In my controller, I'll say this. This. This means that, in my controller, you can see how the layouts work. And, now I have an entire application fall through. And, now I have an entire application fall through. However, I'd like to make it a little bit more than name equals . And, in my controller, I'll say this. This means that, take a request parameter named name, and stick the value as a second parameter for this method view. And, the view says, basically, view object on the right under this name. Now, I have to come here. Name equals . Name. There you go. My name is . All right. So, getting parameters is very easy. Getting uploaded files is exactly the same way. You're basically saying, get a hold of the file. Get a hold of the file. Sending files. Just about, you know, I'm going to walk you through a slightly different location called kitchen sink, which shows more features. But, so far, so far, so good. And, you're using Jetty right now.
Mike Hall Interviewer, UGtastic
Can this work with any other Java container?
Guest Guest
Yes. Yes. This builds into a War file.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Thank you.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Thank you. This built into a War file, which then is deployed, because it's just, it's nothing, there's nothing special about the Jetty is only for the development. In fact, the project that I manage to run on that logic. I originally started on the last page, then I got to build logic. The other website that I'm working on, we developed on Jetty, but then we deployed the top cap. All right. So, let's, let's build a little bit more on the basis that we were here. So, I have this article. It's already working. Articles controller stack.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
Let me copy and paste. Well, let me first do this.
Mike Hall Interviewer, UGtastic
Running a container is fine, but how do I test it? Right? Why don't I write a test for a controller?
Guest Guest
Controllers. I'm going into test Java app controllers, and here, I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay. Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay. Okay.
Guest Guest
I'm going to write a test for my controller.
Mike Hall Interviewer, UGtastic
Okay. Okay. Okay.
Guest Guest
I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. So I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. And I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. And I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a list method from Java library, which is another library that I wrote, which is-- OK. In here, I'll just say . OK. This produces a list. That's all. That's all. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I'm going to write a test for my controller. I know. I've seen it. Oh, there you go. So the idea is this. First of all, let's not look at how I put an article there as I've been performed and we'll look at that. Let's look at the index method because index method is where I have, which gives me a list of articles, right? Supposedly. Articles and I get the list of articles.
Mike Hall Interviewer, UGtastic
So how do I find articles? Article find or order by date map meaning, get me the articles, the most, the latest article first, right?
Guest Guest
And then I stick the result of that into articles.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
So that's classic like integration between activity and active web. Very, very easy to find what you're using, one line of code. A lot of people who write, they kind of complain that they don't actually see active JDPC code because it's usually one line of code to be done.
Mike Hall Interviewer, UGtastic
So, but where does it go from here?
Guest Guest
Index actually has this interesting line of code. Render partial article, collection articles and spacer, spacer.
Mike Hall Interviewer, UGtastic
What's that?
Guest Guest
That's kind of weird. First of all, let's add another article there. No, no, I like, I like . Yeah, it's. Yeah, it was enough. Now I have one article and I have another article and I have horizontal line in between. This happened because this render partial basically doesn't follow it. It says, find a partial page called article. Partials use underscore in front.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
So if I say article here, it's going to be looking for underscore article in here.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
Pass collection articles in it. And then use spacer partial page, which is this one, to interleave iteration. Basically, in between each one, stick the content from this one.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
Of course, all partials are dynamic. I mean, whatever the variables that you pass from the controller are still available and you can make any of those partials as you want. The article itself looks like this. Article author, article title, article content. So, displaying data, like in grids or in some sort of way on the page is very, very easy. And also, refactoring your HTML. HTML designers actually like this a lot because they can say, here in this partial I have kind of a header of my table, here I have footer, and in between I have spacer. They break it down and they know where to look for things.
Mike Hall Interviewer, UGtastic
Okay?
Guest Guest
And on one hand. On the other hand, this render partial is my loop.
Mike Hall Interviewer, UGtastic
Right?
Guest Guest
But it's kind of a loop.
Mike Hall Interviewer, UGtastic
Does that make sense? Right. Anything else you want to cover? Are you sure you can't show Express Pigeon?
Guest Guest
I can't. I can't. I'm working on this pretty advanced project where we built an entire public website for mass email marketing and communication called Express Pigeon. You can check it out. Express Pigeon. You can check it out. Express Pigeon. But the idea is that it's a website built on ActiveGDBC, ActiveWeb, and GDWT. By the way, ActiveGDBC also integrates with GDWT.
Mike Hall Interviewer, UGtastic
Anybody heard of GDWT? Google Web Toolkit?
Guest Guest
Yes. I'm working on this pretty advanced project where we built an entire public website for mass email marketing and communication called Express Pigeon. You can check it out. Express Pigeon. The idea is that it's a website built on ActiveGDBC, ActiveWeb, and GDWT. By the way, ActiveGDBC also integrates with GDWT.
Mike Hall Interviewer, UGtastic
Anybody heard of GDWT? Google Web Toolkit?
Guest Guest
No. No. No. No. No.
Mike Hall Interviewer, UGtastic
Yeah? Okay.
Guest Guest
So the nice thing about GDWT, you can write client-side code, you get a fresh page, and that easily changes. But with ActiveWeb, it does the client-side and the server-side, because the back-end functionality is actually not controlled. So it's a pretty large system. I've been working about a year and a half of the project. But Ivan, you're using your own tool to build that. Yes. And it's not just you. You have a team of guys working on that. So it's-- There's a team of developers working on this fairly large project. And we've been working on it for a year and a half. But this is not the first, not the first, but not the first production system that I've worked on where I actually use that equipment. There's a company called Discovery of Vitality, where we put together a rather large system, multiple websites, back-end functionality, a Linux engine. Horizontal is a scalable JMS system, all built in ActiveGVC and ActiveGVT. There's a lot of services integrated with Johnson and Johnson. Three websites for Vitality. One website for FIMA. Just one website for FIMA is about three to 400,000 members that use that website. So it's not-- in other words, ActiveWeb and ActiveGVC are serious and absolutely ready for production. It's not the particular project I had on Facebook. I think that's important. Yes. I think they always point out when you're looking at these projects, it's like, "Oh, I'm sure somebody wrote this thing. It's cool. " You know, but then it's actually out there and other developers have had to learn how to use it. You know. Yeah, absolutely. And live with it. It's the difference. The teams that I managed that use this stuff, pretty much every day, is using the same stuff for their own projects and whatever day. They don't only use Hypernet, Struts or Spring-OpC. Precisely because it is so much easier to use. And so the idea is to take the productivity of Ruby developer and transport that to Java. And I can reassure you that we were able to achieve the goal which had been proven in real production compliance. We're up a little over 8:30. I do have one quick question.
Mike Hall Interviewer, UGtastic
Sure.
Guest Guest
I've actually done things like this just as kind of a research project so I can appreciate what is needed to make some of the magic happen in there. So when you go in and you go ahead and let's say change your controller class and save it, what gets deployed down the surface? Is it a Java file that gets recompiled or are you letting the IDE compile it and then-- There's no IDE compilation here. The framework on the request, it says, okay, I need to run this controller.
Mike Hall Interviewer, UGtastic
Okay. Then it says, am I in compilation mode?
Guest Guest
Yes. In development mode. In production, that doesn't happen.
Mike Hall Interviewer, UGtastic
Right. Then it says, okay, where is that Java file?
Guest Guest
You can compile it into-- Okay. So this is like what play does in that. But when you-- okay, you're going to get to the production mode. Where I'm trying to go with this is that when I deploy this, do I need to deploy the Java source? No.
Mike Hall Interviewer, UGtastic
Okay.
Guest Guest
So that's the next thing. No. Absolutely not. It deploys as just about any Java program up there. It doesn't really matter. That was one of the things is, you know, there's things here that like the play framework and others to touch on. I think this is a lot more straightforward than things like that. But that was one of the-- Yes, but play framework also compiles more code than active web. Play framework compiles non-controller classes work. And there's also-- This one only compiles controller in the process of controller. So if you have services, it's not going to compile back.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
And you've got instruments and there's a lot of stuff that's going on.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
And even Rails doesn't pick up lib. You have to restart. Well, I could tell you that active web does more than Rails and less than Rails in a sense. You cannot add a controller to a project after Rails server started. You can modify its code, but it has to exist. Oh, okay. At the time and the time, because that's when it sets up routes. In active web, routing is updated. Oh, by the way, routes--I'm showing you routes. Basically, you can do pretty advanced routing system--routing in active web. And routes are--they're defined in Java. And they're recompiled on each request as well. So you can play with routes in a lot of situation. That's nice. And the nuance between production and development mode is the development mode that you're seeing here, so you can kind of do something and immediately see it. And that's really kind of nice. There's a lot of magic that's going on to compiling and redeploying it. But when you actually go ahead and ship it into production mode, you don't--you're not exposed. It's turned off. Right, it turns off. Absolutely. So really, where you need the speed boost and productivity is during the production phase.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
I mean, during the development phase where you want to kind of try this and do that.
Mike Hall Interviewer, UGtastic
Yeah.
Guest Guest
Absolutely. Absolutely. In fact, the parameter to--it's just a Java system property called active reload. If that thing is missing, and of course, we don't have it in production. But even if you had it in production, there's no source of the problem. It's all binary. It's all binary. That's the difference. Major difference between play and active web is that active web goes with standards. It's built in service, built into a warp pile, and drops into any container. And it can gradually be introduced into an existing web project. Whereas play cannot because it doesn't use . But this one's built in . Looks nice. It's a good .
Mike Hall Interviewer, UGtastic
What's the advantage of using this versus doing Rails and JRuby? The advantage of this?
Guest Guest
Rails applications are plagued with, well, plagued with many problems on one hand. So in other words, JRuby, with JRuby, you're going to keep making problems where you can't use a native gem. And you have to find a comparable gem that is written for JRuby, which is going to have a different set of bugs and potentially have a different hit. So the project that I've managed comprised about six, seven Java projects and two URLs projects. We ran and removed projects for about two years. And we switched passages because we ran into so many issues. The other thing is, this is Java. So if you want to stay in Java and not move to Ruby, then you may use Active Web. And the biggest advantage, in my personal opinion, is Java at runtime absolutely kills Ruby. I mean, there's like 19 decades. You need to have, to have a comparable level of throughput, you need to have about ten times as much hosting. About ten times as much hosting for Ruby, compared to Java. Java is a runtime king. And of course, Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it. Active Web is not going to do with it.