views:

480

answers:

7

Hello, I'm trying to create a web user interface for a Java application. The user interface is going to be very simple, consisting of a single page with a form for users to pose their queries, and a results page -- sort of like Google's search engine or Ask.com.

I'm quite familiar with the base API of Java, but I don't have much experience in using Java for Web environments (though I've used ASP.NET), so I'm looking for some advice:

  • What web application server should I use? Note that my interface is very light, and I just want something that is fast, easy to start/reset/stop and (re)deploy my application. Also, I need it to work on multiple environments, namely, GNU/Linux, Mac OS X, and Windows XP/Vista. Additionally, I'm using ant and Eclipse, so it would be great if I could easily add some ant targets for server management, and/or manage the server using the IDE. I've looked into Tomcat and Jetty, and the latter seems to be very light and easy to install and deploy. This is ideal, because the GUI is just for demonstration purposes, and I'll probably need to deploy it in different computers. However, Tomcat has been around for a very long time, and it seems more mature.

  • As for the web pages, Java Server Pages look like a good fit, as they seem sufficiently simple for what I'm trying to accomplish (processing a form and outputting the result), but I'm all ears for suggestions.

  • I also have another requirement, which requires me to explain the "basic" workflow of the application: Basically, I have a class Engine which has a method run(String) which will process the user's input and return the results for display. This class is the core of the application. Now, I'd like to instantiate this class only once, as it requires a lot of memory, and takes a very long time to startup, so I'd like to create it when the application/server starts, and store that reference for the entire span of the application (i.e., until I stop the server). Then, for each user request, I'd simply invoke the run method of the Engine instance, and display its results. How can this be accomplished in Java?


A: 

This is a pretty open ended question, and there are a huge number of possible answers depending on your requirements. The standard way to write web applications is using the JEE platform, which means JSPs, servlets, and EJBs for the business logic. However, there are quite a few popular and valid alternatives such as Spring, Seam, GWT, and even more radical alternatives such as JRuby on Rails. It sounds like your needs are pretty straightforward so you probably want to go with a simple solution like Jetty + Servlets + JSP.

I am assuming your Engine can handle multiple simultaneous requests? If not, you may want to look at figuring out a way to queue requests, such as JMS.

Ken Liu
+4  A: 
  1. App Server. You see Tomcat as heavy in terms of runtime footprint, or amount of learning or ...? I would tend to chose something that has well established integration with an IDE. So Eclipse + Tomcat or Apache Geronimo, perhaps in it's WebSphere Community Edition guise would do the job. From what I've seen these are sufficient for what you want, and the learning curves are really pretty manageable.
  2. Yes JSPs. You may yet find that your presentation needs become a tad more complex. The extra effort of going to JSF might yet pay off - nice widgets such as Date pickers.
  3. In your processing you will have a servlet (or an action class if you're using JSF) that class can have a member variable of type Engine initialised on startup and then used for every request. The thing to bear in mind is that many users will hit that servlet, and hence that engine at the same time. Is your Engine safe to be used from more than one thread at the same time?

To expand in this point. When implementing JSPs, there are two models refered to as (with some inventiveness) as Model 1 and Model 2. See this explanation.

In the case of model 1 you tend to put code directly into the JSP, it's acting in a controller role. Persoanlly, even when dealing with small, quickly developed apps, I do not so this. I always use Model 2. However if you choose you can just put some Java into your JSP.

<%  MyWorker theWorker = MyWorkerFactory.getWorker();
    // theWorker.work();
%>

I woudl favour having a factory like this so that you can control the creation of the worker. The factory would have something like (to give a really simple example)

private static MyWorker s_worker = new MyWorker();
public static synchronized getWorker() {
       return s_worker;
}

Alternatively you could create the worker when that method is first called.

In the case of model 2 you naturally have a servlet into which you are going to put some code, so you can just have

private MyWorker m_worker = MyWorkerFactory.getWorker();

This will be initialised when the servlet is loaded. No need to worry about setting it to load on startup, you just know that it will be initialsed before the first request is run. Better still, use the init() method of the servlet. This is guranteed to be called before any requests are processed and is the servlet API architected place for such work.

public class EngineServlet extends HttpServlet {

private Engine engine;

// init is the "official" place for initialisation
public void init(ServletConfig config) throws ServletException {
     super.init(config);
     engine = new Engine();
}
djna
Thanks for the comments. 1) Heavy in the sense that it seems to have many features that I don't need, and it also seems to require a few extra steps to install. On the other side, from what I've seen from Jetty, all it takes for it to start is to run a `java -jar start.jar`. There's also a nice contrib project which allows me tu run my application just by using `java -jar jetty-runner.jar application.war`, which is pretty cool, as I want to run the web interface for demonstration purposes, on different computers. However, Tomcat seems to have a really solid reputation, so it's a tough choice.
JG
2) It really is a very simple interface for a (fairly) complex application, and I don't think I'm really going to need more advanced widgets, but thanks for the suggestion. Eventually, I'll need to integrate some API's (such as Google Maps) on the results page, but I'll probably just code the javascript in the JSP page for that.
JG
3) Can you provide me an example for that, using JSP? From what I've read so far, I need to "activate" the `load-on-startup` of the servlet configuration, so that it is loaded when the server starts. But how exactly can I access the member variable `Engine` of the servlet, from inside a JSP? Basically, I have a page `A.jsp` with an input text field, whose content is goin to be passed using `GET` to page `B.jsp`. In this page, I need to get that `Engine` instance, invoke a method using the content of the `query string`, and output the results.
JG
Also, about the thread-safeness issues, I don't really do much updates except when I create the `Engine`. Everything else is really just heavy processing. I do, however, have a class that uses `FutureTask` to paralelize some operations, but they are just using a Web API to collect and return results.
JG
1). It does sound like Jetty does what you need. I've never used it, so can't say more.2). I Understand. 3). Added to the answer. Afraid the code is not tested, but the concepts should get you started. The key idea is that you are just using standard Java rules for initialisng classes.
djna
I've edited my question, based on your suggestions.
JG
+1  A: 

Assuming this isn't a one-off application which doesn't need any kind of updating/maintenance in the future, I'd recommend you do the view layer with Apache Wicket for the following reasons (read the short infoblurb from the homepage first):

  • Since Wicket separates the view layer and works in the model layer of MVC in a clean way, it can be easily explained that view is completely separated from rest of the application and Wicket's IModel interface is used to link the data from controller layer to the view layer in a reliable way. Thus your controller layer maybe a single application singleton as long as you use it that way.
  • Wicket code is stunningly easy to maintain, also extending functionality of your web application can be done very easily since it's OOP framework instead of markup mixed with other kind of markup which expresses code.
Esko
Thanks for the comments. It seems neat, but I really just need to have a "form => submit => process => show results", as it's just for demonstration purposes of the application.
JG
+2  A: 

The technology you need to learn is the Sun Java Servlet specification since that is what ALL non-trivial java webservers implement. This enables you to write servlets which can do all the things you need server side. You can then develop against any container working well with your iDe, and deploy on any other container working well in production.

You also need to learn basic HTML as you otherwise would need to learn JavaServer Faces or similar which is a rather big mouthfull to create the submit button you need with the other entries in a HTML form.

For your Engine to work you can create a servlet with a singleton in web.xml, which you can then call. Be absolutely certain it is thread safe otherwise you will have a lot of pain. For starters you can declare your invoking servlet synchronized to ensure that at most one call of run() is active at any time.

Thorbjørn Ravn Andersen
Thanks for the comments. Yes, that's what I thought so. My goal is to have a light container where I can easily deploy the application for demonstration purposes. However, I may eventually need to host the application permanently, possibly using a different container.I do know HTML and other web technologies (CSS/Javascript, et cetera), as I have used them before with ASP.NET. However, I'm kinda new to Web application development in Java.
JG
Which container is almost irrelevant if you write a conformant Java Web application. Tomcat usually has excellent IDE support which is invaluable when developing. Right now, I am sorry to say you have a bit of learning to do :-)
Thorbjørn Ravn Andersen
Yes, I know, I've been reading some articles on the subject, no need to be sorry ; ). Also, if you can, please comment the code that I've added to the question.
JG
A: 
  1. app server: tomcat
  2. web page: jsp
  3. You need a class which is Singleton or class with static method. Word of caution: Beware of race condition. You might need to use synchronized keyword for those methods involving update/modify operation.
janetsmith
You should definitively let the web container know and manage the thread unsafe servlet. Syncrhonized let the JVM do it instead which might lead to an unresponsive web container.
Thorbjørn Ravn Andersen
A: 
  1. Jetty is a very lightweight container, and perfect for your development scenario.

  2. You might want to look at Wicket for your rendering side; you seem more comfortable doing code-like tasks as opposed to straight UI.

  3. The pattern you are describing is the Singleton pattern. Take a look at the google results for singleton in java.

joeslice
A: 

EDIT: So far, I've decided on the following:

  • Web Application Server: Jetty;
  • Java Server Pages for the views;
  • Based on the suggestions of @djna, I've read a couple of articles regarding Model 2, and I came up with this solution (which I haven't tested yet, because I need to finish my application before moving into the interface):

form.jsp

<form action="/servlet/EngineServlet" method="GET">
  <input type="text" name="text" />
</form>

EngineServlet.java

public class EngineServlet extends HttpServlet {
  private Engine engine = new Engine(); 
  // does this make sure engine only gets instantiated one time in the entire lifespan of the web application; from what I've read from the servlet lifecycle, it seems like it, but I'd like to hear opinions

  public void doGet(HttpServletRequest request,
                    HttpServletResponse response) {
    String text = request.getParameter("text");
    ResultBean result = engine.run(text);
    request.setAttribute("result", result);
    RequestDispatcher dispatcher = request.getRequestDispatcher("result.jsp");
    dispatcher.forward(request, response); 
    // what's the difference between forward, and request.sendRedirect() ?
  }    
}

result.jsp

<div>The result was: ${result.text}</div>

What do you think of this solution? Any problems that may not be obvious to someone coming from a J2SE background ? I also wrote some doubts that I have in the code as comments. Thanks.

JG
Initialising engine: is "cleaner" if done in servlet init() method, I've amended my answer to say that. The servlet life-cycle is discussed in http://www.j2ee.me/j2ee/tutorial/1_3-fcs/doc/Servlets4.html You will see that there will be exactly one instance of the servlet class at any one time, so in your code there will be one instance of Engine **at one time**. The app server could choose to finalize and re-init your servlet. I've never seen an App Server do that, but to be 100% sure put the responsibility for being a singleton with the Engine. See next comment.
djna
It might be essential that there be no more than one Engine instance. Or it might behighly desirable from a memory consumption perspective. In either case I would say that you should not rely upon the client (the servlet in this case) to police that there be one instance. Instead use a factory as shown in my answer. The serlvet says "Give me an Engine" the factory says "use this one", and can take responsibility for ensuring that the Singleton Engine is used. This solution is resilient to unusual servlet life cycle events, and also to future maintenance, what happens if you have two serlvets?
djna
Forward: the servlet does some work, gathers some data, and then passes the **same** request on to the JSP for rendering. The browser sees the url of the servlet. Redirect: the servet sends a response to the browser saying "don't display this, instead send a request for **this** page", a different URL. You use the latter when the original request did some work that you don't want to accidentally repeat (eg. pay some money). By sending a redirect the browser's history can have a sequence of "GET" display requests, with no "POST" actions, that if resubmited would repeat the work.
djna
Thanks a lot, your pointers and suggestions allowed me to learn a lot about the Web/J2EE side of Java. I'm accepting your answer. Just comment, if you can, my Model 2 implementation above to see if there's something that could be ameliorated.
JG
Oops, you just did; thanks again.
JG