4

I have an application that is undergoing massive rework, and I've been exploring different options - chug along 'as is', redo the project in a different framework or platform, etc.

When I really think about it, here are 3 major things I really dislike about java:

  1. Server start/stops when modifying controllers or other classes. Dynamic languages are a huge win over Java here.
  2. Hibernate, Lazyloading exceptions (especially those that occur in asynchronous service calls or during Jackson JSON marshalling) and ORM bloat in general. Hibernate, all by itself, is responsible for slow integration start up times and insanely slow application start up times.
  3. Java stupidity - inconsistent class-loading problems when running your app inside of your IDE compared to Tomcat. Granted once you iron out these issues, you most likely won't see them again. Even still, most of these are actually caused by Hibernate since it insists on a specific Antlr version and so on.

After thinking about the problem... I could solve or at least improve the situation in all 3 of these areas if I just got rid of Hibernate.

Have any of you reworked a 50+ entity java application to use mongo or couch or similar database? What was the experience like? Do you recommend it? How long did it take you assuming you have some pretty great unit/integration tests? Does the idea sound better than it really is?

My application would actually benefit in many areas if I could store documents. It would actually open up some very cool and interesting features for this application. However, I do like being able to create dynamic queries for complex searches... and I'm told that Couch can't do those.

I'm really green when it comes to NoSQL databases, so any advice on migrating (or not migrating) a big java/spring project would be really helpful. Also, if this is a good idea, what books would you recommend I pick up to get me up to speed and really make use of them for this application in the best way possible?

Thanks

Community
  • 1
  • 1
egervari
  • 22,372
  • 32
  • 121
  • 175
  • starting your question with a rant isn't very good style. You're covering way too much ground to make a specific answer possible and objective. – Mat Apr 25 '11 at 11:54
  • 1
    2 years since you asked the question! So, what did you end up doing ? Did you move to any NoSQL database ? – 2020 May 21 '13 at 21:59

3 Answers3

1

In any way, your rant doesn't just cover problems with the previously made (legacy) decision for Hibernate but also with your development as a programmer in general.

This is how I would do it, should a similar project be dropped in my lap and in dire need of refactoring or improvement.

It depends on the stage in your software's lifetime and the time pressure involved if you should make big changes or stick with smaller ones. Nevertheless, migrating in increments seems to be your best option in the long term.

Keeping the application written in Java for the short term seems wise, a major rewrite in another language will definitely break acceptance and integration tests.

Like suggested by Joseph, make the step from Hibernate to JPA. It shouldn't cost too much time. And from there you can switch the back-end to some other way of storage. Work towards a way of seperating concerns. Pick whatever concept seems best, some prefer MVC while others might opt for CQRS and still others adore another style of segmentation/seperation.

Since the JVM supports many languages, you can always switch to any of those or at least partially implement functionality in more dynamic languages. This will solve part of the problem where you keep bumping into the "stupidity" of Java, while still retaining the excellent optimizations of current JVMs at runtime.

In addition, you might want to set up automatic integration tests... since the application will hopefully never be run from your IDE, these tests will give you honest results.

Side note: I never trust my IDE to get dependencies right if the IDE has capabilities to inject its own libraries into my build or runtime path.

So to recap in short: small steps; lose Hibernate and go more abstract to JPA; if Java becomes stupid, then gradually switch to a clever language. Your primary concern should be to restructure the code base without losing functionality, keeping in mind to have an open design which will make adding interesting and cool features easier later on.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
Gressie
  • 507
  • 2
  • 7
  • You're making a lot of assumptions about this project. First of all, there is a whole suit of unit and integration tests. It is very well tested. Even though the project uses hibernate directly, I fail to see how using JPA is going to help me. I could do this though. I don't know what it will save me as it's basically Hibernate anyway. The code itself, besides Hibernate, is extremely well refactored and is designed very well. It's also extremely performant. Code quality isn't the problem. Also, IntelliJ IDEA is loading dependencies from Maven directly - it is not manually done. – egervari Apr 25 '11 at 15:20
  • @egervari Making assumptions was necessary to give an coherent answer. 1) You did cover too much ground, like Mat mentioned on your question. 2) JPA abstracts the project. You can slot in a Facade there, something speaking JPA on one side and something else on the other. Suggestions have been made for a commercial product, but of course there are other options. 3) Refactoring and redesign never stops. 4) Opinions on code quality might differ. 5) Enforce that specific ANTLR in your pom, problem likely solved. Have a nice day. – Gressie Apr 27 '11 at 06:27
  • 2) There's no need to abstract it out though. I already have a DAO layer. Two abstractions isn't going to improve things really. 3) Of course. 4) Yes, but this code is quite good. 5) Already did this a very long time ago. I just don't really know why developers need to go through the hassle of doing it. It is the developer's expectation that if they include 3 libraries that require 3 versions of ANTLR and CGLIB that Maven figures out the best one to use. It doesn't a lot of the time. It is honestly fair to question why we should have to debug this and fix it in the first place. – egervari Apr 27 '11 at 20:21
  • 2) what I meant is the rewrite from Hibernate to NoSQL is huge, time consuming and might give more trouble than going JPA first. After all, NoSQL might not be the solution and then the codebase needs another major rewrite. In my opinion using JPA would be a safe intermediate step until the decision to go solely NoSQL. Developer decision, I prefer slow transgression. 5) It's nearly impossible to properly decide which version to use for Maven, so it probably takes the safest bet (lowest version) and gives you executive power to make a better decision. – Gressie Apr 28 '11 at 05:52
  • Maven behaves differently... Having come across situations where Intellij IDEA loads all the jars through maven and everything works... then I go to deploy it to tomcat on the production server, and lo-and-behold, there are classpath errors. I know this isn't entirely maven's fault (classpath specification is simply horrid), but maven makes some bad decisions that caused the error in the first place. And of course, it could take an hour or so to figure out what's wrong and fix it - which is harder since the production and development env's are behaving differently. Very frustrating honestly. – egervari Apr 28 '11 at 11:55
0

Well, much depends on things like "what exactly are the pain points with Hibernate?" (I know, you gave three examples...)

But those aren't core issues over the long haul. What you're running into is the nature of a compiled language vs. a dynamic one; at runtime, it works out better for you (as Java is faster and more scalable than the dynamic languages, based on my not-quite-exhaustive tests), but at development time, it's less amenable to just hacking crap together and hoping it works.

NoSQL isn't going to fix things, although document stores could, but there's a migration step you're going to have to go through.

Important: I work for a vendor in this space, which explains my experience in the area, as well as the bias in the next paragraph:

You're focusing on open source projects, I suppose, although what I would suggest is using a commercial product: GigaSpaces (http://gigaspaces.com). There's a community edition, that would allow you to migrate JPA-based java objects to a document model (via the SpaceDynamicProperties annotation); you could use JPA for the code you've written and slowly migrate to a fully document-oriented model at your convenience, plus complex queries aren't an issue.

Joseph Ottinger
  • 4,911
  • 1
  • 22
  • 23
0

All of those points are usually causing problems due to incompetence, rather than hibernate or java being problematic:

  • apart from structural modifications (adding fields or methods), all changes in the java code are hot-swapped in debug mode, so that you can save & test (without any redeploy).

  • the LazyInitializationException is a problem for hibernate-beginners only. There are many and clear solutions to it, and you'll find them with a simple google or SO search. And you can always set your collections to fetch=FetchType.EAGER. Or you can use Hibernate.initialize(..) to initialize lazy collections.

  • It is entirely normal for a library to require a specific version of another library (the opposite would be suspicious and wrong). If you keep your classpath clean (for example by using maven or ivy), you won't have any classloading issues. I have never had.

Now, I will provide an alternative. spring-data is a new portfolio project by springsource, that allows you to use your entities for a bunch of NoSQL stores.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • LazyInitializationException can be solved in most cases, but not all cases. When using Spring's testing framework, they don't show up unless you turn transactions off, and in that case, your dbunit no longer works. I want to add that json mapping and asynchronous calls to mailers can throw these exceptions that open session in view will not solve. So no, this is not due to incompetence. This is just pain in the ass detail that you shouldn't have to put up with. It would be more manageable if we had a way to specify loading strategies in Hibernate directly, but no such thing exists. – egervari Apr 25 '11 at 15:14
  • Also, I was using maven. You are pretty disillusioned if you think maven actually solves the classloading problem. It doesn't. Try using Joda time with the hibernate extensions - oh what fun. There are a bunch of other combinations of frameworks and libraries that cause conflicts maven has no clue how to fix. – egervari Apr 25 '11 at 15:15
  • @egervari there _are_ loading strategies in hibernate - they are called lazy and eager. If you set everything to eager, you won't have any problem. So is it still not incompetence? – Bozho Apr 25 '11 at 15:21
  • As for maven - it won't solve the problems because some libraries do not define properly their dependencies. But I do use joda-time with its joda-time-hibernate and hibernate, in production, and no - I didn't have problems. (well, joda-time-hibernate is not upgraded to work with the latest version of hibernate, but with a little amount of work it is working) – Bozho Apr 25 '11 at 15:21
  • and, apart from telling you why you are wrong, I gave you an alternative that you asked for, after all. So I don't think a downvote is due. – Bozho Apr 25 '11 at 15:22
  • @bozho: Yes, there are loading strategies, but they are APPLICATION-WIDE. Setting them to eager also makes everything super slow when you work with nested trees of complex data. It is not practical to make them eager by default. The only solution is to make everything lazy. But sometimes you wish it behaved as if you set it to eager in the mapping for 'some' parts of the application and not others. JPA actually has something for this precise use-case, but Hibernate does not. – egervari Apr 25 '11 at 15:30
  • As for Maven, this is my point. You said that Maven solves classloading problems... and I'm complaining that in reality, it doesn't solve them. Now you've just admitted as to why. I knew why - it doesn't change the fact that it has problems. This creates all sorts of weird issues - especially if you load maven in your IDE and then deploy into Tomcat. All sorts of crap happens. – egervari Apr 25 '11 at 15:31
  • Hibernate is a full-featured JPA implementation, so there's no such thing that exists in JPA but doesn't in hibernate. If you want to sometimes load some collections, then use `Hibernate.initialize(..)`. – Bozho Apr 25 '11 at 15:35
  • 1
    As for maven, it's a problem that may happen if both the library guys and you happen to overlook something. But if any of the two parties is careful, the problems can be avoided. IDE vs Tomcat - it's the same, unless you use some profiles. The jars are located in the same directory on your machine. – Bozho Apr 25 '11 at 15:37