1

I'm developing a web app using Javalin. I have multiple controller classes that handle my routing for me. Each controller is supposed to be associated with a single POJO/DB Table type. So for instance I have an Employee controller that routes and displays pages related to Employee POJOs. The Employee controller (on the backend) references primarily an Employee Dao Service which then queries the Employee table in the database. So far so good, right?

My question is, some of my frontend pages MUST include details from other tables, which means I am creating an instance of other DAO services within my Employee controller, for instance, sometimes I need GroupDaoService and LocationDaoService becuase several employee pages also display group and location information. I imagine this gets a little memory intensive because every time a different page is loaded, a different set of DaoServices are being used. So my question is, should these DaoServices be Singletons? Would having a single EmployeeDaoService make sense? The underlying database connection pooling class that these different DaoServices make use of, is already a Singleton. Should I follow this same pattern with my DaoServices?

Would it make sense performatively to change my DaoServices into Singletons?

Here's an example portion of the EmployeeController that will need to implement 3 or 4 other types of DAO besides EmployeeDao, which is what sparked this question.

`    public static Handler serveUserDetails = ctx -> {
         List<Integer> recCounts = mainSVC.getTotalRecords();
         Map<String, Object> pdata = new HashMap();
         String userID = ctx.pathParam(":id");
         pdata.put("numEvents", recCounts.get(0));
         pdata.put("numSites", recCounts.get(1));
         pdata.put("numUsers", recCounts.get(2));
         pdata.put("user", userSVC.getEmployee(Integer.parseInt(userID)));
         pdata.put("groups", groupSVC.getGroups());
         pdata.put("schedules", schedSVC.getSchedules());
         pdata.put("webuser", W_EMP);
         ctx.render("/templates/userdetail.vtl", pdata);
    };`
TheFunk
  • 981
  • 11
  • 39

1 Answers1

1

Yes that makes sense. Services are normally singletons. I wouldn't see a good reason to need multiple instances within a web application on a single node. If you use Spring for your dependency injection, singleton is already the default scope.

Of course this assumes the services are stateless, i.e. don't hold session or request related data.

Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60
  • All of my services need to handle a single piece of stateful information related to the web user's session. The last line W_EMP is my "webuser" object which holds this information. However, this information is used by the controllers for display purposes only. Is there a good way to handle that kind of stateful information and still convert the Dao services to singletons? – TheFunk Feb 08 '19 at 14:08
  • You should not keep the webuser as a field in any of your singleton components since web applications are usually multi-threaded. If you did, a user could be presented with the details of another user. It does not matter that the data is read-only, since it is still different data for different threads/users. – Adriaan Koster Feb 08 '19 at 15:52
  • Woops sorry. I misspoke. My controllers need to handle that information. I've created a single setSessionInfo function in each of my controllers (which are not singletons afaik. My DAO services though, are now Singletons! Thanks! – TheFunk Feb 08 '19 at 16:14
  • 1
    Beware: Controller are traditionally singletons (and should be stateless) for the same reasons that services should be. – Adriaan Koster Feb 11 '19 at 14:48
  • Could you possibly link me to some sample code where a stateless controller serves dynamic content based around session info? At the moment my controllers are not singletons just because I need the same webpage to look different depending upon who's looking at it. i.e. if the user is an admin they should see their username on the screen and admin underneath their name and a few extra buttons, whereas a standard user would see their name and picture but no admin label or extra buttons. – TheFunk Feb 11 '19 at 16:13
  • 1
    This pattern is really standard. Most MVC examples should show this. Content served by a controller should not be stored in fields inside the controller. It can be obtained from the HTTP session (this used to be quite standard, but not common anymore due to scalability issues amongst other things), a local repository (e.g. database) or a call to a remote service. – Adriaan Koster Feb 11 '19 at 16:16
  • 1
    HttpSession is the standard solution to associate state with a user. It relies on a cookie called the 'session cookie' to know the session ID. The web container (like Tomcat for example) stores all the active sessions in memory. This can become quite the performance bottleneck if the application stores a lot of data in the session. Also, when using load balancing or fallback nodes to improve scalability, sessions are troublesome because users always need to hit the node which knows their session. So either requests need to be routed to the right node, or sessions need to be migrated. A pain. – Adriaan Koster Feb 11 '19 at 16:21
  • See here for a simple example of using sessions: https://www.javacodegeeks.com/2013/04/spring-mvc-session-tutorial.html Note that nowadays server sessions is not used that much anymore. Everybody is storing all the session state in the single-page JavaScript application running in the browser. – Adriaan Koster Feb 11 '19 at 16:24