I am currently developing an Java EE application with an JSF frontend and struggled with some major page speed problems. In this article I want to give you some ideas that may improve your application in matter of the loading time.
Architecture of the application
First of all I want to give a short overview on how the architecture of the application looks like. I have the view in which I use the JSF technology and for each view the corresponding controller – and if needed some view-models for input as well. Besides that there is a controller for navigation and another one for authorization, which I use in multiple views.
The controllers are pretty dumb and delegate pretty much everthing to the services. Their only tasks is to prepare the data so I can access them properly in the view. This way I have the opportunity easily change the frontend to another technology. The services have knowledge about the domain and also do the database access. For that I use JPA as it is the standard in Java EE 7.
Choose the right scope
The first thing I’ve optimized was to change the scope of my controllers. There are mainly four different scopes as you can read in this article: Scopes in Java CDI. Almost everywhere I used the request scope so everytime there is a new request a new controller is created. For the authorization controller this means, that there is no way to cache information, which definitly won’t change while in the same session. After changing this one to session-scoped, the user loaded from the database can easily be accessed without any further request to the database and the authorization checks are performed only once when the session starts.
In my application the navigation controller mostly stores constant values but this also doesn’t need to be request-scoped as well. Every user can use the same navigation controller since it stores no data which is correlated to the session, so I annotated it was an application scope.
Use a cache for database results
As I already mentioned, it is very helpful to store data from the database in some sort of a cache. If you want to check, whether or not the user is an administrator for the application, you can store a boolean value in a session scoped controller. You can do the same when you need a list of all users. In my case there won’t suddenly exist a new user so I read the list once and store it in a variable as well.
Use lazy load on JPA entitys
Both previous things were in fact correlated to minimize request to the database. At this point there is one important thing you can configure. In an entity class you can specify when the relationships should be resolved. Let’s say you have a user class and he belongs to different groups. The standard procedure of JPA would be to load the user from the database and after that load all groups, the user belongs to, as well. But in case you just need user information and the groups are ignored, they don’t need to be accessed from the database – or later, when there is a method really using them. To control such behaviour there is the fetch-attribute for the @OneToMany annotation.
- @OneToMany(fetch=FetchType.EAGER) will instantly load all relationships
- @OneToMany(fetch=FetchType.LAZY) will load the just entity and the relationships only when they are needed