I currently have a basic j2ee website. Currently, a jsp frontend gets data from the backend (the java program, lets call it object “Score”). The backend gets this data from a web site.
<% Main m = new Main(5); %>
<table style="width: 100%">
<tr>
<th align="left">NBA</th>
<th style="text-align: right"><%=m.getTime("nba")%></th>
</tr>
</table>
<% Iterator itrNba = m.getNbaM().entrySet().iterator();
for (Map.Entry<Integer, Match> entry : m.getNbaM().entrySet()) {
Match value = entry.getValue(); %>
However, this only happens once. If the user wants new data, they have to refresh the page, the backend will run the algorithm to populate some objects (HashMaps), and the jsp displays the values.
The backend data is sports scores and I want this to be a live feed. Therefore I have to make the back end poll the source, and the front end poll the backend (not necessarily the same intervals either).
How can I make my data objects persist? With my current implementation, every time the page is loaded, a new Score, when Score should be the same for all clients (the frontend jsp). So I made my data objects static and I put the main entry point in a loop, and it isnt working.
Im thinking my main java Scores object needs to be run as a service. Do I need to use servlets here?
Is there an easy way to accomplish what I’m describing?
6
So, lets think about how the current approach works.
- You’ve got a jsp that is invoked
- It creates a
Main
object. - The
Main
object goes out and does some work and provides this information via its fields or method after control has returned. - The jsp accesses these fields or methods and presents them to the end user.
This has a number of issues with scalability that you’re seeing. You could be doing what appears to be a denial of service on the target site of the data. Thats not good (though that said, they’ve probably got better caching and network than you do – still, it isn’t good). The work that you do on your own system isn’t shared between requests and so every request has to do the work again (even if nothing is changed).
There are two parts to this application, and as written there is a clear separation between the two. That makes things a little bit easier.
If this is transient data (you don’t need to persist it for more than a short period of time), the easiest thing to do would be to store it in the Context. There are several contexts available – Application (all of Tomcat), Servlet (that servlet’s info), Session (one user’s session info), and Request (note: this is framework dependent – you’ve got things like Spring, PrimeFaces, or your own ad hoc).
Now, I’m going to start out with you could do it this way, but its a way that is rather… undisciplined. The lack of discipline may make it easier to implement now, but harder to extend properly later. So make sure you keep reading after seeing the “it could be done this way”.
You could create an object that conforms to the JavaBeans naming standards that has the data and the timestamp (for caching) and stick it in the application context.
It would look something like:
package com.mycompany;
public class MyBean {
private Date date;
private int score;
public Date getDate() { return date; }
public void setDate(Date arg) { date = arg; }
public int getScore() { return score; }
public void setScore(int arg) { score = arg; }
}
Register it as part of the context of the application in web.xml and then have Main
look it up, check to see if it needs to fetch new data or not, and if so, fetch the data from remote and store the data in the bean. A bit more of this spelled out in Tomcat Standard Resource Factories in the Tomcat docs. Essentially, you are creating a Singleton that you can access. I’m not going to say that this is a good approach, but it will work.
The thing is, thats kind of ugly. Yea, you can store the data there, but its still kind of ugly. You shouldn’t have any problem with a simple class like the one described, but if you have something more complex, its possible to get race conditions where two requests both decide that they want to fetch the data and each store part of the data which is mismatched.
This also really doesn’t scale. If you have two servers (for redundancy) you could get one with the data from 10 minutes ago and one from 5 minutes ago. And you hit the page and you get one answer, then you hit it again and you get another answer, and then you hit it again and you get the first answer. With game scores, this could be very confusing.
And here’s where I’m going to start getting architect astronauty.
You need to have the data somewhere. Put it in a database. It could be a classic relational one like MySQL; or if the data fits the appropriate model, a NoSQL database of some sort might be appropriate. The specifics of which NoSQL database would be the right one depends significantly on the type of data you are storing and how you want to access it (and remember, if you are dealing with multiple databases for redundancy, the eventual consistency of some flavors of NoSQL can bite you hard).
So, you’ve got a database. You also have a process that runs outside of the Tomcat container that puts the information in it. This could be a quick script or its own Java application. Its just fetching data from some source and reshaping it to fit in the correct database. It runs once a minute or so (depending on what your needs are). Thats all, it fetches data, and puts it in the database.
Now, instead of Main
fetching the data from the site, it fetches the data from the database. This is fast. Frankly, you shouldn’t be doing it from a separate class at this point – just fetch the data. It also fetches a complete record when it does so that you don’t get race conditions in there.
You could stick it right in the JSP, though thats seen as rather ugly. I’ll tell you up front that this offends my sensibilities.
What you’ve got right now is a model 1 application. It works, and its easy to write and deploy. But it mixes the business and presentation logic in the JSP. You’ve also got very limited sharing of code between JSPs which means there is lots of potential code duplication which makes maintain a mess.
You really should look at a model 2 approach which has a servlet handling the ‘traffic cop’ aspect of the web application, a data access layer that fetches the data from some data source, and the jsp that gets the request from the servlet, pulls out the appropriate info stored in beans and uses Expression Language (often written EL) instead of scriptlets in the jsp.
Yes, this is a bit more ceremony in creating it. However it’s a well known and standardized model that another Java programmer could come in and immediately recognize and build on with less work. It also makes it feasible to test small parts of it to make sure it all still works (JSPs are notoriously difficult to unit test).
You could do this with straight up servlets (which is quite doable), or look at using a framework such as Spring, Stripes, or Play to make it easier to work with. The frameworks put a structure around the code and how it is written – adding some discipline to the layout and enforcing it to ultimately make a higher quality product.
1