I'm trying to use Spring in my already using Hibernate application, but I've found a problem. After having everything working, I've started running some tests and I've seen that the memory consumption of the application never starts growing, it never decreases, which is really bad and forces me to restart the server. It gets from 120MB to 500MB in just an hour of normal use.
I'm sure I have something bad configured, but I don't know what or how to detect it.
If I run the netbeans profiler I can see that every time I call a servlet I get a new surviving generation, which I suppose may have something to do whith sessions not being closed or something similar.
The most relevant parts of my configuration are:
Then I have a DAO and an InterfaceDAO for every bean. The application works great, the only thing is that it's consuming a lot of memory and there's no way I can put it in production unless I fix this. I'm aware that I haven't read as much documentation on Spring as I should have, but I'm sure someone in here will be able to point me out where my error might be. I'm quite in a hurry to get this working so I'd really apreciate any kind of help.
Thanks a lot!
Just a few random things that might be worth checking:
a) Are the http sessions getting closed and disposed of? ie is logout really killing the http session
b) Is your DAO closing hibernate sessions?
c) If you repeatedly log in, and straight away log out without doing anything, do you still see this problem, or does it only occur when the logged in user has tried to do something meaningful?
Not sure I can without profiling tools, but could be a few useful places to start.
For every domain class I've got a DAO and an interface:
And all these DAO's extend from 2 generic ones:
That's all I've got. I don't have any filter to control Hibernate sessions or anything because as I understood it, this should be taken care of automatically. I don't know where I read that or if that makes any sense. I really hope I misunderstood that and someone can point me how should I do it.
I apply lazy-loading based on relationships with annotations. Most of them are set to lazy but I need some others to be eager. The managing of the httpSession is what I don't know how do I have to manage. I've got the applicationContext defined and then on every servlet I invoke
Is that what you refer to?
As I said before, I use the netbeans profiler, but I don't manage to get clear results from it. I can see that every time I invoke a servlet I get an extra living generations, which is bad and I suppose that is what is causing my problems, but I can't manage to track down where exactly this living generation comes from.
When user enters into your application a session is maintained. You might add user details, Query result or something else to your session. Lets say you have added query result to your session but you didn't remove it from session when you are done. and this repeats many times. Other thing is, when user log out from your system, you should invalidate the session.
I am just wondering how do you use WebApplicationContext?
I just got confused. Of course I manage the session, and I invalidate it when the user leaves. I tracked it with the profiler and it has nothing to do with my memory consumption problems.
I don't know if I said it but the applications worked perfeclty and then I decided to use Spring, that's when my memory consumption problems started. So I just assume I have a misconfiguration problem, probably related to transaction mamangement.
As of the Web ApplicationContext, the typical use in my application is :
And then use the DAO classes to create, find, delete, etc objects from the database.
I hate to say this, but Emili, from what you posted, it appears you did everything correct. your configuration is very clean. As a side note, since you called your file applicationContext.xml and put it in the WEB-INF directory, you do not have to include the context-param.
Personally, I wouldn't have the Servlets calling the DAOs directly, I would always have a service layer between the two, and the service layer being where my Transactions declarations reside. Which might match your assumption that it could be transaction management related.
How was your previous version structured differently than when you added Spring?
Thanks for your reply. I kind of hate to have the configuration correct, because I still can see that the living generations never stop growing on the profiler. The good news is that after tweaking a little the app server the memory consumption has lowered quite a bit. Which I also hate because know I won't take this problem that seriosuly now.
The difference when I didn't have Spring is that I didn't have a DAO and a DAO Interface for every domain class, I had just one Generic DAO.
Now that I've been thinking a lot about this I've realized that maybe this problem existed before and I just didn't notice it.
I think it's very interesting what you say about the service layer but I don't know exactly how you would implement that, can you give me some hints?
OK, so what is the responsibility of a Servlet. It really is just to be the endpoint of a Web Request, the request comes in and you get the information in the request and session out, and as soon as you do that, pass it off to another Java Class to do the actual Use Case. Keep all business logic and data access out of the Servlet code. If you put business logic and data access code in the Servlet, you are tightly coupling that code to the Servlet, so lets say you want a Web Service, or some other remote access, you can't because it is in the Servlet.
So a service class is the demarcation of the business logic. So if you are doing say a User registration, then the request comes into the servlet, you get the data out and create your domain classes from that data, then create a Service class instance and call a method on it, say registerUser(User user). That method will call out to your DAOs.
Hope that helps clears out the layered architecture which will help create a loosely coupled application.
Make your Service classes, define them in your applicationContext.xml have your DAOs injected into the Service classes, and in your Servlets lookup your Service classes from the ApplicationContext, just like you are doing now with the DAOs.
How do you implement your service layer? Do you implement it using one of the ways, I have mentioned or something else?
They are just POJO Java classes, nothing special about them, and they are configured as Beans in application context, just like other POJOs. It is just the layer where you declare your transaction scope and is the start of a business use case. It is just like the concept of a Stateless Session Bean, but a POJO and not EJB.