Sunday, April 8, 2012

Just how thin can a framework be? ActiveJDBC vs Hibernate.

When people talk about thickness of a framework, and it being lightweight, what do they actually mean?

I think there needs to be a few parameters to be looked at, for instance:
  • Level of intrusiveness into your code (subjective)
  • Speed of execution (objective)
  • Code elegance (subjective)
  • Physical weight - total size of dependencies for "Hello world" (objective)
  • Stack depth (objective) - depth of a stack in case of exception coming from a lower level technology

Lets consider the level of intrusiveness with Hibernate and ActiveJDBC. I personally of course prefer ActiveJDBC because it has almost no annotations, no configuration files, but most of all it has no third party object such as Hibernate Session that actually operates on entites.

Here is a code in Hibernate entity:

@Table(name = "employees")
public class Employee implements Serializable {
    public Employee() {}
    @Id
    @Column(name = "id")
    @GeneratedValue
    Integer id;
    @Column(name = "first_name")
    String firstName;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", first_name='" + firstName + '\'' +
                '}';
    }
}



Usage of entity:
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
List employees = session.createQuery("select e from Employee as e").list();
session.close();

And here is comparable code in ActiveJDBC:

Model:
public class Employee extends Model{}

That is right! One line of code, and nothing else.

Usage of model:
Base.open("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test_db", "user1", "*****");
List employees = Employee.findAll();
Base.close();

As you can see, ActiveJDBC uses a different paradigm: models (entities in AJ talk) operate
on self, without requiring a third party class.

I think that by code intrusiveness, ActiveJDBC is certainly thinner than Hibernate.

Speed of execution: I built a simple non-scientific test in both ActiveJDBC and Hibernate.
The code inserts 50 thousand records into MySQL table, then reads all 50K records from it.
This is performed on my laptop, which is: MBP 2009, Core 2 Duo CPU P8700 @ 2.53GHz,
with 8G RAM, 256G SSD and Ubuntu running natively.
Hibernate insert: 16057 milliseconds
ActiveJDBC insert: 9630 milliseconds

Hibernate select: 50000 records in: 1874 milliseconds
ActiveJDBC select: 50000 records in: 836 milliseconds

As you can see, ActiveJDBC is significantly faster given exactly the same task:
Insert: ActiveJDBC took 40% less time.
Select:ActiveJDBC took 54% less time.

Code elegance: while this is super subjective especially considering the fact that I'm the author of ActiveJDBC API, I hope most people will agree with me simply by looking at code above.

Physical weight: This is a total size of all dependencies a simple application requires.
Here ActiveJDBC wins hands down.
ActiveJDBC dependencies:

-rw-r--r-- 1 igor igor 137026 2012-04-05 12:03 activejdbc-1.2-SNAPSHOT.jar
-rw-r--r-- 1 igor igor 33795 2012-04-05 12:03 javalite-common-1.2-SNAPSHOT.jar
-rw-r--r-- 1 igor igor 495944 2012-04-05 12:03 mysql-connector-java-5.0.4.jar
-rw-r--r-- 1 igor igor 23659 2012-04-05 12:03 slf4j-api-1.5.10.jar
-rw-r--r-- 1 igor igor 7599 2012-04-05 12:03 slf4j-simple-1.5.10.jar

Total size: 704K

Hibernate dependencies:
-rw-r--r-- 1 igor igor 443432 2012-04-05 12:13 antlr-2.7.6.jar
-rw-r--r-- 1 igor igor 26361 2012-04-05 12:13 asm-1.5.3.jar
-rw-r--r-- 1 igor igor 16757 2012-04-05 12:13 asm-attrs-1.5.3.jar
-rw-r--r-- 1 igor igor 282338 2012-04-05 12:13 cglib-2.1_3.jar
-rw-r--r-- 1 igor igor 175426 2012-04-05 12:13 commons-collections-2.1.1.jar
-rw-r--r-- 1 igor igor 38015 2012-04-05 12:13 commons-logging-1.0.4.jar
-rw-r--r-- 1 igor igor 313898 2012-04-05 12:13 dom4j-1.6.1.jar
-rw-r--r-- 1 igor igor 208048 2012-04-05 12:13 ehcache-1.2.3.jar
-rw-r--r-- 1 igor igor 2321639 2012-04-05 12:13 hibernate-3.2.7.ga.jar
-rw-r--r-- 1 igor igor 365546 2012-04-05 12:13 hibernate-annotations-3.5.6-Final.jar
-rw-r--r-- 1 igor igor 66426 2012-04-05 12:13 hibernate-commons-annotations-3.0.0.ga.jar
-rw-r--r-- 1 igor igor 2566731 2012-04-05 12:13 hibernate-core-3.5.6-Final.jar
-rw-r--r-- 1 igor igor 100884 2012-04-05 12:13 hibernate-jpa-2.0-api-1.0.0.Final.jar
-rw-r--r-- 1 igor igor 8812 2012-04-05 12:13 jta-1.0.1B.jar
-rw-r--r-- 1 igor igor 495944 2012-04-05 12:13 mysql-connector-java-5.0.4.jar
-rw-r--r-- 1 igor igor 52150 2012-04-05 12:13 persistence-api-1.0.jar
-rw-r--r-- 1 igor igor 22338 2012-04-05 12:13 slf4j-api-1.5.6.jar
-rw-r--r-- 1 igor igor 7583 2012-04-05 12:13 slf4j-simple-1.5.6.jar

Hibernate requires a whopping 7424K, more than 10 times of ActiveJDBC! Even if I remove MySQL driver, this comparison is still not in favour of Hibernate.

Stack depth: this is simply counting methods on the stack trace, which gives you a pretty good idea of a framework depth. In order to see this for ORM, I mangled the SQL to cause an exception in the DB layer, and here are results:

Hibernate depth:
1276 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1054, SQLState: 42S22
1276 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Unknown column 'age' in 'where clause'
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2536)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at hibernate_test.SelectAllHibernate.main(SelectAllHibernate.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'age' in 'where clause'
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3176)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1153)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1266)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
at org.hibernate.loader.Loader.doQuery(Loader.java:802)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2533)
... 13 more


ActiveJDBC depth:
Exception in thread "main" org.javalite.activejdbc.DBException: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right
syntax to use near 'where age > 1' at line 1, Query: SELECT * FROM employees WHERE where age > 1
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:936)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2870)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3176)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1153)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1266)
at org.javalite.activejdbc.DB.find(DB.java:408)
at org.javalite.activejdbc.LazyList.hydrate(LazyList.java:304)
at org.javalite.activejdbc.LazyList.size(LazyList.java:454)
at activejdbc_test.SelectAllActiveJDBC.main(SelectAllActiveJDBC.java:13)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to use near 'where age > 1' at line 1
... 16 more


When you count the number of lines in exception stack trace betwen the client code (your code) and low level technology
(MySQL in this case), you will have an idea of a framework depth. For ActiveJDBC it is 3, for Hibernate it is 15.
So, Hibernate is about 5 times thicker than ActiveJDBC.

One might say: so what, why do I care about the size of dependencies, depth of stack trace, etc. I think a good developer
should care about these things. The thicker the framework, the more complex it is, the more memory it allocates,
the more things can go wrong. Besides, simply by requiring certain dependencies, it can limit your options
of using up to date versions of the same dependencies, creating headaches on classpath.

Bottom line is: choose your frameworks wisely

cheers

30 comments:

Anonymous said...

Wow how biased can you get?? Talk about spreading misinformation your comparisons are completely incorrect and one sided. Something that would be obvious to any hibernate developer. I wont mention everything (ill be here all day otherwise) but if you're going to compare dependencies at least compare it to THE LATEST VERSION and not the one from 2006. You've even piled in loads of optional dependencies. Also are you telling me that your framework can map databases from classes with NO fields or getters/setters!

I'm sorry but you won't get any respect from anyone by writing articles like this

Igor Polevoy said...

Dear Anonymous, I contemplated to publish your comment or not, but then decided to do so and provide a reasonable feedback.

1. How biased am I? Of course I'm biased. I'm biased so much so that I spent the last three years of my free time developing ActiveJDBC, accepting contributions from the community and donating it all back.

2. The version of Hibernate I use is 3.6.0-Final. You can pull the sources of these examples from here: http://dl.dropbox.com/u/43668168/DBExamples.zip. At the time I put together this example, the version 3.5.0-Final was the latest, and then I migrated to 3.6, which was pain because they did not make things backwards compatible. Now, I just repeated the same tests with 4.1.1-Final and results are about 10% worse than 3.6.0-Final in terms of speed!

3. Dependencies. I used mvn dependency:copy-dependencies to collect them. Guess what, with version 4.1.1-Final, Hibernate now pulls a whopping 21M of dependencies. Now, to be fair, I can exclude one after another to slim it down, but this is a job for a framework developer, why should I guess what Hibernate needs and what it does not?? If you know exactly what dependencies are optional, let me know, but no matter what, with the hibernate-core lib at over 4.4M in size, which is 31 times bigger than ActiveJDBC *without dependencies*!

4. You are making a blank statement: "Something that would be obvious to any hibernate developer." - exactly what??

5. You could take a few minutes to familiarise yourself with ActiveJDBC so as not to sound ignorant: "Also are you telling me that your framework can map databases from classes with NO fields or getters/setters!"
Yes, and YES, read the docs.

Now, lets cool off, and see how we can have a conversation. This post is obviously subjective, which I mention many times, but the goal is not only compare ActiveJDBC and Hibernate, but also to prompt people to explore the lightweghtedness (if there is such a word!) of a framework before using it.

cheers

Anonymous said...

Hello Igor, here another Anonymous, but with a different view,

I like the article. I d say ActiveJDBC is a library for the known ActiveRecord pattern.

Hibernate/JPA on the other side are commercial backed frameworks which wrap and hide stuff from the software engineer so the companies behind it can sell their app servers and their special gui tools. besides that it includes alot of abstraction and special caching which doesnt fit anywhere, so alot of shoehorning happens.

i wish there was no need for sl4j, java.logging was enough for my casual usage so far.. i m using jooq right now.. but i m allways interested in similar libs..

ty for the good job

Igor Polevoy said...

Anonymous #2, thanks for comment, I actually collaborate with Lukas E., the creator of jooq here and there.. nice to see people try alternatives to mainstream!

GOzzie said...

Igor, can you please also provide an example as to how AJ can be used with JSF.

You know, thanks to Hibernate or some equivalent ORM tool, one can directly populate an entity with data e.g.

How would this work for AJ?

Thanks

Anonymous said...

Nice work.. keep it up. :)

Java Tutorial said...

Hi Igor,

This post is interesting. But one thing which is not clear is:Hibernate has the very popular HQL (Hibernate Query Language). Do we have something similar in ActiveJDBC.

Suggestion: Hibernate is from JBoss so there is a dedicated site for updates, latest news but when I searched for ActiveJDBC, I get it hosted on code.google.com, wiki page and referred on some blogs. Would be interesting if you donate the project to Apache and contribute from there which I think will increase popularity of ActiveJDBC

Igor Polevoy said...

GOzzie: my focus has been on ActiveWeb since 2010: http://code.google.com/p/activeweb/, I personally think that JSF is evil. However, I will try to put together a simple prototype, should not be hard at all, I'm pretty familiar with JSF.


Java Tutorial: I agree, the site could have been better, however if you look at the issue tracker, and the forum, you will see that issues are resolved within 24 hours and question on support forum are answered usually within hours.

However, your suggestion to donate this to Apache sound really interesting, I never thought of this, thanks for food for thought :)

Igor Polevoy said...

Java tutorial: sorry, missed your question about HQL - ActiveJDBC does not require to learn a new language - that is counter-productive, one of the design principles: "No need to learn another QL - SQL is sufficient", take a look here:
ActiveJDBC Programming Model.
You can browse complete documentation here as well:
Features

If you have specific questions, ask here:
ActiveJDBC Google Group

tx

Mauricio Porras P said...

For the most general purpouse, what would you recommend, AJDBC or jOOQ?

Thank you in advance.

Igor Polevoy said...

Mauricio Porras P: I personally do not have experience with Jooq outside looking at the documentation on the site. I'd say that if your schema is new, you can use ActiveJDBC, if you have a legacy schema, and it is crazy, you might want to look at Jooq. With ActiveJDBC you too can write raw SQL, but Java compiler will not help you.

Paolo said...

Hi Igor,
I've discovered ActiveJDBC just a few days ago, and I've really appreciated its simplicity and distance from the "enterprise approach"...

I'd like to propose it's adoption in our company, but I was wondering if there's a plan about a stable artifact release, since our policies are very strict about it.

Many thanks for your great work!

Paolo

Igor Polevoy said...

Paolo, I do have plans to release a stable version 1.2 and deploy it to central repo, it is just being on snapshot version gives you advantage to always have the latest/greatest:). However, a stable release will come out in a few weeks.

Anonymous said...

Have to say, this article and the comments above this one makes me sad, very sad.

First anonymous raised valid points on using a historic version of hibernate. Then someone else claimed that Hibernate is just a reason for RH to sell app server. Are you kidding me?

First off, modelling your entity. Those annotations there are metadata about your table(s). It can also be used to build your table(s) (think iteration 0). The fact that you glamorize AJDBC for supporting mapping your entities as well.. not really mapping but giving them out as maps. (There is a hibernate MAP mode for this as well.)

Using Map for everything is however a huge antipattern. You lose code completion on pressing "." after a reference. You lose all documentation about the features of the class. You essentially don't have a class, you have a complex Map wrapper.

Does AJDBC support transitional persistence? You know, you save entity A, and the save is cascaded to all not-yet-saved entities referenced by A? Or the same with updates, save_or_updates, deletes?

How is optimistic locking handled/supported? Manually? How about lazy loading of refenced entities or collections?

Please, let ActiveRecord (anti-pattern) stay in the RoR world with all "the opinionated developers". Please don't refer this project to anyone, they'd be better off using JDBC through spring jdbc templates, until they realize that their DAO code is becoming hibernate, and then hopefully switch. Hopefully though such people will continue writing ruby code.

Igor Polevoy said...

The Latest Anonymous: your statements about ActiveJDBC are all incorrect. I think you should read the docs on the subject before posting. ActiveJDBC might be perceived as a map because of dynamic setters and getters, but here is where similarity ends. It is also no brainer to see that if there is a company behind a framework, it helps make it more popular, what is wrong with that? ActiveJDBC does not have support for transactions... for a reason, and there is a page for that. It is a pass through model, not-yet saved entities simply do not exist. Optimistic locking is not manual, etc.

What is really sad is that people with negative views base them on this thread instead of making their opinion based on fact i.e. - read the docs, try the thing, then post with knowledge.

As far as ActiveRecord should stay in RoR - this is a laughable suggestion, if people had no opinions, we'd still be jumping from tree to tree.

Igor Polevoy said...

GOzzie., I put together a small project that integrates ActiveJDBC and JSF: activejdbc-jsf.zip

It is based on older version of JSF, but will give you enough ideas on how to use it. It includes listing of data from a table, as well as insert of data from a form, which also includes built-in validation from ActiveJDBC. You will see that even with JSF, you write absolute minimum of code to access DB if you use ActiveJDBC

Ron Smith said...

Enjoyed the article, keep it up! The Java world has a tendency to over-complicate solutions, so I really appreciate the focus on simplicity and keeping things light-weight as possible.

I had the same question regarding interoperability with frameworks that depend on JavaBeans compatibility, or at least the getter/setter convention. I see you address it here: http://code.google.com/p/activejdbc/wiki/SettersAndGetters#No_"standard"_setters/getters???. Basically, create the getters and setters yourself, calling the map-style getter and setters within them. Having something to generate these one-time based on DB metadata would be useful, but not a big deal.

Igor Polevoy said...

Ron, thanks for comments. As far as generating setters and getters, there is an effort going on by a community member Kalyan Mulampaka who is going to contribute a code generator soon, I hope.
When I started usign ActiveJDBC in 209, I was overly excited and I did not use setter and getter wrappers, but then got a push back from the team I managed, they all wanted to have these, and over time I realized they were right. Java IDE provides a tremendous amount of support and productivity when these methods are present. I now always use them.

cheers

Lieven Doclo said...

I've used a lot of persistency frameworks, including those following the ActiveRecord. As thin frameworks go, this is really not a bad solution. However, I really must support the comment regarding the map-based access for the properties of the table. Nowadays, I use QueryDSL in combination with JPA, which enables me to create type safe queries (code completion, yay!). With your solution, if someone changed the physical model, your code will break at runtime (with Hibernate you can do model validation). Not really refactor friendly if you ask me. Even if you write your own getters and setters, you'd still run into issues when someone changes the code.
Another thing I don't really like is the fact that your physical model details ooze into your code. In most enterprise development models I've seen, the database isn't handled by the developers and most DBA's use naming conventions on their fields.
So in short, very nice effort, might use it in smaller projects, but you have to admit: you lose a lot of the safety nets that JPA+QueryDSL solution provides.
To finish: you're comparing two very different things: Hibernate is an ORM. ActiveJDBC is not. It's a (very nice) abstraction layer on top of JDBC with some ORM-like features, but comparing ActiveJDBC with Hibernate is like comparing Jetty to Glassfish.

Igor Polevoy said...

@Lieven: I'd have to politely disagree with some of your statements. First, ActiveJDBC is an ORM -
this is an actual object-to-relational mapping. I think the reason for reacting like this to
it from some Java developers is because Hibernate has been dominating the landscape for
so long, and people have started thinking that this is the only way to do ORM.
”If it does not look like Hibernate must not be an ORM” :)
Look outside a but - Rails for instance to start. There are many ways to skin a cat. At the end of the day, all we need is to read data from DB, put data back, and write as less code as possible, right?
I do not understand why people are so hung up on "map" - likeness and getters and setters. ActiveJDBC has a ton of other features.

Now to safety. DBAs controlling schema is OK for ActiveJDBC, all conventions are overridable. In fact, the first commercial implementation of AJ was in 2009 for a health insurance company where we did not control anything.
Safety: For me the main safety is not compiler, it is tests! If type safety was the main protector, people would not be able to write high quality software in dynamic languages.
You are also making strange statement about "physical model details ooze into your code".. where did you get this?

Anyhow, I think you are hung up on terminology - I call this ORM, if you want to call this anything else, no problem, Jetty can run JMS, EJBs, after all - the lines are blurred.
Please, give ActiveJDBC a spin, and see for yourself. After a couple of days of using, you'd laugh about setters/getters and ORM noncense.

Lieven Doclo said...

I'll certainly give ActiveJDBC a try. But as you said, ActiveJDBC is based on Rails features. For those accustomed with Ruby and Rails, the usage of maps may not be such a big problem. However, anyone who has worked for example with the SDO spec (see Apache Tuscany) knows what a pain in the ass dynamic data objects can be and are more than happy to accept the 'weight' of getters and setters if it provides a very well needed safety net. And you can't argue that ActiveJDBC entities are dynamic data structures.
Anyway, I can certainly believe ActiveJDBC fills a corner of the Java ecosystem (for example for former Ruby/Rails developers). However (I can't believe I'm saying this), JPA is a formal spec and a part of the JavaEE spec. Smaller companies may give it a spin, but the size of companies I'm in it doesn't stand a chance. It's not proven nor endorsed by large companies. For prototyping, I'd most certainly consider ActiveJDBC.
As for the physical details oozing in your code: you need to know the exact database field names when writing database specific code (at least, your example don't say otherwise) and each developer writing data access code needs to know the physical layout of the DB. With JPA, you have your model abstraction (logical vs. physical model). If a DBA decides to change the name of the field, you only need to change 1 annotation, whereas with ActiveJDBC you'll have to change each line that accesses that field. Ouch. And something else: due to the fact that there are no fields, getters or setters on your model, javadocs are basically useless. Anyone reading the code also needs a printout of the database layout in order to understand the data model behind the code.
As for getters and setters, when you use clean , pure ActiveJDBC with say, JSF, you're almost obliged to create a separate model (the dreaded DTO) containing getters and setters, because JSF models rely heavily on the JavaBean spec, and map between those 2 models. Again, you can write the getters/setters on the ActiveJDBC entities (but then you might as well use JPA if you ask me), but for example with JPA, that's just the touch of a button to generate those. Due to the map nature of ActiveJDBC, you can't generate those (unless you'd write your own IDE plugin). So on one side you're saying DTO's aren't needed thanks to ActiveJDBC, but once you're working with frameworks that rely on the JavaBean spec, they become a necessity.

Igor Polevoy said...

@Lieven, sorry to say this, but you are missing the mark here. It is clear that you are still hung up on lack of getters and setters... well did you look at this page: http://code.google.com/p/activejdbc/wiki/SettersAndGetters which explains that we are writing setters and getters, which will provide all the type safety you get with JPA.
As far as JPA being a standard, sorry to say, but your comment brings about really bad emitions, I blogged about my attitude towards Java standars here: Stop Hating Java 2

Then you talk about JSF -- oh, man, why is Java plagued with such crapshot technololgies, and even makes them into standards??? I would never touch JSF with a ten foot pole. However, here is a sample ActiveJDBC/JSF project I put together for the poor souls out there having to deal wioth JSF and wanting somehow to aliviate their misery: activejdbc-jsf.zip, as you can see, it has type safety, and uses ActiveJDBC built-in validations. What it does not have it a crapload of configuration and barely any code.

Now, in case you are not aware of it, but I also run another OSS project: ActiveWeb and I use that exclusively for all my web development.
In any case, the getters/setters/standards etc conversation started and ended for me in 2009, since then, I built a number of commercial production systems and sites for corporations based on these technologies, so I do not need to question viability .. or readiness.. or value of ActiveJDBC and ActiveWeb. In fact, the teams I manage tell me point blank that we would not be able to develop these as fast and at this quality level had we used so-called "standard" technologies.

As for you, well the only way to get converted it to try it out.

Still friends? :)
cheers

Anonymous said...

Hi Igor,

Pretty interesting framework. recently i made two choices for my back-end db stack. interestingly, one was jooq and other is activejdbc.

Thank you for the framework.

Dejan Lekic said...

ActiveJDBC would be close to perfection if it could use natural keys instead of insisting on surrogate keys. Yes, I am in that other group of RDBMS users who prefer natural keys to surrogate keys except in those RARE cases when surrogate keys are a good idea.

I see lots of comments from the Hibernate community here - I must say I am not surprised. - You either love Hibernate, or hate it... I am not a Hibernate user myself, but I would just say that it is not a good idea to compare the two. Hibernate offers much, much more than ActiveJDBC, so it is a no-brainer to understand that it requires more in terms of dependencies.

Overall, I like ActiveJDBC and use it whenever I need something "higher level" than the JDBC... :)

Igor Polevoy said...

Dejan, ActiveJDBC uses surrogate keys, correct. However you can also use composite keys if you like. ActiveJDBC will simply ignore them. Some people use composites to ensure data integrity.
While I agree that Hibernate offers much more, I also think that the 80% of common tasks needed for day to day development is handled by ActiveJDBC. The rest 20% makes any product that much more complicated.
Also, comparing the two is perfectly normal, as they solve the same problem of writing code to access relational data.

Lukas Eder said...

Hi Igor,

Finally I had some time to react to this post of yours.

While I agree that low complexity may correlate with short stack traces, I don't think that high complexity and long stack traces necessarily depend on each other. In fact, if complexity is high AND there are long stack traces, that's actually a good sign, in my opinion.

Of course, your comparison is absolutely valid, as you claim that ActiveJDBC has little complexity and thus short stack traces.

Here's my post: http://blog.jooq.org/2013/11/21/deep-stack-traces-can-be-a-sign-for-good-code-quality/. Interested to hear your opinion!

Igor Polevoy said...

Liukas, I responded on your post too.
Also, I think ActiveJDBC is pretty complex internally (includes bytecode instrumentation ), but manifests itself as a simple framework to developer. That is what I meant. Additionally, it is not trying to solve 100% of crazy use cases, and does not implement what is already implemented by the lower layers (JDBC driver, database), which makes it simpler. At the same time, I have no method grater than about 30 lines: ActiveJDBC Sources
I was just using depth of stack in comparison as one of the indicators of thickness of a framework. I think we are in agreement here.

Lukas Eder said...

> responded on your post too.

Glad you mentioned that. It was "recognised" as spam :|

> I think we are in agreement here.

Yes, we are

Federico Peralta said...

Hi! First, regarding the article, I think @Lukas Eder has a point: low complexity <=> short stacktraces, but high complexity and long stacktraces are not dependant on each other.

I do however like the spirit of both the article and ActiveJDBC very much (I haven't tried ActiveWeb): you have to consider what framework you are using on your project, and how the framework affects the project. (Here I mean maintainability, simplicity vs complexity, code readability, performance, etc).

Now, a little background before my question. I've been developing web applications in java for more than 10 years. I've tried jsf, spring mvc and plain jsp & servlets, and I dislike them all. Regarding ORM/persistence layers/jdbc wrappers, I've tried plain sql over jdbc, Hibernate, spring jdbc and a forgettable company-made "framework" (it was a wrapper really) around Hibernate's criteria. While I don't hate them (except for the forgettable company-made wrapper), I find them to be of little-to-medium usefulness: configuration is terrible, complexity increases, either you have to do a lot of stuff for a simple sql sentence (if sql over jdbc) or the ORM does what it wants with the database, you have the typical session problems (i.e. lazy initialization exception), dettached criterias, prepared statements, result sets handling, etc, and above all, we yet have to arrange the code and the architecture to fit the ORM, which I think is an absolutely ridiculous thing.

So just by chance, I got introduced to the Ruby world and was amazed by its simplicity; you just need 1 minute to have a production-ready web application! I'm a java guy, though, so I was reticent to introduce ActiveRecord in a java project. You know, it's said to be an anti-pattern because it violates the single resposibility principle, and because instrumented entities are hard to test, etc. So first question is: what do you have to say regarding these anti-pattern criticisms?

Now, my project: Spring RESTful services provided by an embedded Jetty server, complex business logic (not just trivial CRUD operations), layered architecure, semi-to-quite normalized mysql database, Hibernate ORM (non-JPA), and an anemic model. We decided to change the ORM, since the persistence layer is becoming unmanageable, and are considering options. I like ActiveJDBC very much, but:

1. How can we make it work inside a Spring context with a BoneCP connection pool DataSource?

2. We can't (and don't want to) replace the whole persistence layer in one single pass; we need to follow a step-by-step process. So, can Hibernate and ActiveJDBC co-exist in the same application, with the same database, using the very same connection pool, and most important, sharing the same transaction?

3. Precisely, what about Spring @Transaction? (We'll definitely keep that one, it's very handy to have transactionality managed in the services layer instead of in the persistence layer)...

As you can imagine, I have to negotiate with the team and with the manager, and I'm not totally free; I have to pose alternatives, but can't be very radical; ORM must be replaced gradually, and differences must be measurable.

Thank you very much for this product and keep up with the very good work and effort!

Igor Polevoy said...

@Federico, this is more than a comment on a blog, it requires a conversation. I spoke with our guys, and I think we can give you some good advice. Would you mind posting this on a framework forum to kick-start the conversation:
https://groups.google.com/forum/#!forum/activejdbc-group

Thanks
igor