Novice Tomcat design pattern question

T

TwelveEighty

I have a heavy duty java server application that is collecting
information from computerized sources and processing and archiving
events in real-time. The configuration on this app is currently done
through RMI by exposing certain objects as remote objects on which
clients can invoke actions (add, remove, change, etc.).

I like to add the ability to communicate with the server application
via web services, so Tomcat seems like a good "best practice" choice.
However, from a design perspective, it seems like the Tomcat server
becomes the main "host" application from which other java classes can
be "activated" based on requests from clients.

The only way I currently see to "bolt on" the Tomcat web services is
to have two virtual machines running, one with my application and the
other being the Tomcat server. However, that means that all
communication between the main app and Tomcat needs to go through RMI,
because there are two VMs. This sounds very inefficient, I much rather
have the whole application running in a single VM.

Is there a design possible where I can incorporate my application into
the same virtual machine that is running Tomcat? More specifically:

1) Can I "bootstrap" my own java classes inside the Tomcat environment
during the Tomcat startup process? If so, does all handling need to
take place in the constructor of my classes, or can I invoke specific
methods?

2) Is there a RMI registry created during the Tomcat startup that I
can register my existing RMI classes with, to keep the existing RMI
functionality I have today? If so, can I change its port through
configuration?

Thanks.
 
A

Arne Vajhøj

TwelveEighty said:
I have a heavy duty java server application that is collecting
information from computerized sources and processing and archiving
events in real-time. The configuration on this app is currently done
through RMI by exposing certain objects as remote objects on which
clients can invoke actions (add, remove, change, etc.).

I like to add the ability to communicate with the server application
via web services, so Tomcat seems like a good "best practice" choice.
However, from a design perspective, it seems like the Tomcat server
becomes the main "host" application from which other java classes can
be "activated" based on requests from clients.

The only way I currently see to "bolt on" the Tomcat web services is
to have two virtual machines running, one with my application and the
other being the Tomcat server. However, that means that all
communication between the main app and Tomcat needs to go through RMI,
because there are two VMs. This sounds very inefficient, I much rather
have the whole application running in a single VM.

Is there a design possible where I can incorporate my application into
the same virtual machine that is running Tomcat? More specifically:

1) Can I "bootstrap" my own java classes inside the Tomcat environment
during the Tomcat startup process? If so, does all handling need to
take place in the constructor of my classes, or can I invoke specific
methods?

2) Is there a RMI registry created during the Tomcat startup that I
can register my existing RMI classes with, to keep the existing RMI
functionality I have today? If so, can I change its port through
configuration?

There are various ways to achieve what you want.

You could start a thread calling your apps main method in a
startup servlet.

If the calling code can get a reference to the app, then they
can call whatever methods they want.

Your Java code can create a registry.

Arne
 
J

Juha Laiho

=?ISO-8859-1?Q?Arne_Vajh=F8j?= said:
....
You could start a thread calling your apps main method in a
startup servlet.

Another way to achieve the same would be to write and declare
a ServletContextListener to handle the startup. This would have
the added benefit of also being able to shut down the "external"
server cleanly when Tomcat is being shut down.

One slight issue with both of these ways is that the "external"
server is only started up at the point where Tomcat already
starts accepting requests - so it could be that the first requests
through Tomcat arrive at a time where the "external" server has not
yet completed its own startup.

It might be good to have a way to provide a way for the "external"
server to tell the Tomcat webapp whether it is ready to process
requests or not. This could be done for example by setting an attribute
in Tomcat servlet context, and having the webapp check the existence
and the value of this attribute.
 
T

TwelveEighty

Another way to achieve the same would be to write and declare
a ServletContextListener to handle the startup. This would have
the added benefit of also being able to shut down the "external"
server cleanly when Tomcat is being shut down.

After Arne's post, I started looking into this and I noticed that
there is also an init() and destroy() method on the HttpServlet
itself. What would be a better approach, to use the
ServletContextListener, or use the init() and destroy() methods for
startup and shutdown of the "external" server?
 
O

Owen Jacobson

After Arne's post, I started looking into this and I noticed that
there is also an init() and destroy() method on the HttpServlet
itself. What would be a better approach, to use the
ServletContextListener, or use the init() and destroy() methods for
startup and shutdown of the "external" server?

A ServletContextListener doesn't have to have any code in it to handle
(or at least actively reject) servlet API calls and has much simpler
instantiation guarantees ("once", as opposed to "once, unless you
implement specific marker interfaces or the configuration says
otherwise"). If all you're doing is reacting to the servlet container
lifecycle, I'd use a Listener.

-o
 
A

Arne Vajhøj

Juha said:
Another way to achieve the same would be to write and declare
a ServletContextListener to handle the startup. This would have
the added benefit of also being able to shut down the "external"
server cleanly when Tomcat is being shut down.

Servlet destroy method should work for that as well.

But yes a context listener was definitely also a way of doing that.

Arne
 
A

Arne Vajhøj

Owen said:
A ServletContextListener doesn't have to have any code in it to handle
(or at least actively reject) servlet API calls

Neither does a startup servlet. It inherits a couple of do nothing
methods.
and has much simpler
instantiation guarantees ("once", as opposed to "once, unless you
implement specific marker interfaces or the configuration says
otherwise").

Not doing anything special giving the desired effect is not that bad.

Arne
 
O

Owen Jacobson

Neither does a startup servlet. It inherits a couple of do nothing
methods.


Not doing anything special giving the desired effect is not that bad.

Arne

Oh, I agree with you. Doing it from a servlet *works fine*. I just
find it more cluttered; even if you inherit the default
implementations of doGet and doPost, your lifecycle servlet still
exposes them. I'm a big believer in minimal exposed interfaces.
 
A

Arne Vajhøj

Owen said:
Oh, I agree with you. Doing it from a servlet *works fine*. I just
find it more cluttered; even if you inherit the default
implementations of doGet and doPost, your lifecycle servlet still
exposes them. I'm a big believer in minimal exposed interfaces.

Eventually context listener will probably replace startup servlets.

Startup servlets really are a hack.

But they have served me well for many years.

Arne
 
J

Juha Laiho

TwelveEighty said:
After Arne's post, I started looking into this and I noticed that
there is also an init() and destroy() method on the HttpServlet
itself. What would be a better approach, to use the
ServletContextListener, or use the init() and destroy() methods for
startup and shutdown of the "external" server?

I took a quick glance at the Servlet Specification, and the language
lawyer in me found at least one potential issue; the servlet container
is free to release any servlet that is not currently running, and I
didn't see any mention about load-on-startup servlets being any
exception to this. So, a servlet marked load-on-startup will be loaded
on context startup - and thus, its init() will be called. However,
unless I missed something, the container is also free to unload the
servlet on the next second, and at that point would call destroy()
on it.

Realistically, I consider the above to be highly unexpected behaviour,
and haven't seen any container do it. But as long as the spec allows
it, you should consider it a valid scenario.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top