Re: Where to start with a webapp that is not really a webapp
On Fri, 26 Jun 2009, Andrew wrote:
I have an app that is currently a Junit test but I want to convert it
to a program that will run 24x7, i.e. a server. The dev env that I am
in means the app uses many, many 3rd party jars. Loads of them. We
also use several frameworks including spring and hibernate. There are
many properties and beans that form part of our lengthly
configuration. I have pointed out that ideally this app would be a
standalone server. In the past I designed such apps with a main
entrypoint and wrote a little shellscript to kick them off using the
java VM with appropriate CLASSPATH settings. However, I have been
asked to make it a webapp. I am looking for help.
There are certain advantages to it being a webapp. Deployment is a
snap, the jar issue is neatly taken care of and I don't need to write
a shellscript either since tomcat will run the app for me. But the
question is "how?". I haven't been doing java very long and working in
webspace is very new to me. My server actually has nothing to do with
the web, the webapp route is purely to simplify deployment and the
general runtime env.
The only other webapps I have seen are either using spring MVC or are
a bean that listens to a JMS queue for ever. I can see how these work.
In the first case tomcat starts the app in response to a URL pattern
match and the entrypoint is the http request for the matching URL. In
the second case the bean is a singleton and starts when tomcat starts.
Since it listens to the JMS queue immediately and never shuts down
there is no problem. My app does not fit into either of these
categories. So what kind of entrypoint would I have? Obviously not a
URL-related one. Does that mean it would have to be done as a
singleton referred to in the bean configuration?
Your basic problem is that your app is completely unsuited to being a web
app. The fundamental nature of web components is that they sit there and
respond to web requests. A message-driven bean is similar, but it responds
to JMS messages. Web services respond to SOAP calls. EJBs respond to RMI
calls. Your app doesn't do any responding.
I think, in fact, that there's a mistake in your very first sentence -
needing to run all the time doesn't make it a server. It might make it a
daemon, but it's not serving anyone, so it's not a server. All the J2EE
infrastructure is about serving, so it's not really right for you. I think
the original idea of a standalone app is the right one.
However, it sounds like the need to make it a web app is external - it's
not a design decision, it's a requirement. In which case, a web app it
must be. And since you're talking about MDBs, i assume that by "webapp"
you actually mean "J2EE component".
In which case, the problem is finding something to respond to. My
suggestion would be timer events. See:
http://java.sun.com/javaee/5/docs/tutorial/backup/update3/doc/Session4.html
You can create a recurring timer with:
long intervalInMilliseconds;
TimerService ts;
ts.createTimer(0L, intervalInMilliseconds, null);
Annotate your main method (IYSWIM) with @Timeout. Put the timer creation
in a method annotated with @PostCreate. Then, as soon as the bean gets
loaded, it will go into an infinite loop doing whatever it is it needs to
do.
The only problem then is causing it to be loaded. I don't think the
container will create an instance on deployment - i think the bean has to
be referenced first. I'm not aware of anything you can write in the
deployment descriptor which changes this, but i'm pretty ignorant when it
comes to EJB, really. It would be simple enough to create a client which
connects to the EJB and pokes it over RMI to get it loaded. I don't think
it even has to do RMI, actually - i suspect a JNDI lookup will be enough.
You'd then need to run the client after deploying the component.
Alternatively, rather than creating the timer in a @PostCreate method, put
a start() method on the bean, and do it in there. Have the service-starter
client call that method. You could then add a stop() method which cancels
the timer, in case you decide your loop shouldn't be infinite after all.
You could even then add a status() method, which lets the client app check
whether the component is working properly - that triad of operations is a
pretty common in service-control tools. You often see a restart() too.
A related approach would be to look at something like Quartz, which is a
more sophisticated scheduling service (and funnily enough, which pretends
to be, or perhaps even is, a JMS source, so your job would be an MDB,
getting a message whenever it was time to run). With that, there are ways
of configuring scheduled jobs which wouldn't require you to explicitly
start the service - it would be run automatically as long as it was on the
schedule. JBoss comes with Quartz built in; i don't know about other app
servers.
tom
--
.... the gripping first chapter, which literally grips you because it's
printed on a large clamp.