(I had a similar need but couldn't find anything in the way of a tutorial,
so I rolled my own. Probably more detail than you wanted, but fwiw...)
We have a single Ant-based project that can deliver a Restlet Component in
all three of these modes. We use Guice, but I'm sure that adapting the
technique for Spring would be straightforward.
The jar target just produces a jar, *jarname*.jar, which is runnable with
"java -cp *jarname*.jar;lib/*.jar -D*sysprops* org.example.tim.Main". (We
could take the extra step of jarjar-ing everything into a single executable
jar, but we haven't had the need.)
The dist target creates the jar and puts it and the supporting configuration
files into a deployable distribution hierarchy, installable with YAJSW
(similar to Java Service Wrapper).
The war target puts the jar along with a web.xml into a war that can be
deployed in a servlet container.
The key ingredient is a Main class that extends GuiceServletContextListener
with:
@Override protected Injector getInjector() {
// Guice Injector created here from a list of Modules, including a
locally-defined ServletModule
// that calls serve("/*", MainServlet.class, initParamMap), where
initParamMap includes
// these two entries:
// org.restlet.component -> MainComponent.class.getName()
// org.restlet.autowire -> true
// The first of these fools Restlet's ServerServlet machinery into
thinking that the
// Component is being supplied by init-param, when in fact it is
being provided by
// overriding createComponent. This is necessary to keep
ServerServlet from thinking
// it's in a different "mode". (See ServerServlet docs.)
// The second of these will automatically consume the servlet
context path from the request URI
// so that you can deploy the war under a named context other than
root without having
// to handle your request paths differently than you do in
standalone.
return Guice.createInjector(stage, ...);
}
This Main class is listed in the web.xml:
<listener>
<listener-class>org.example.tim.Main</listener-class>
</listener>
<!-- Also have the standard GuiceFilter incantation here. Not sure it's
necessary, though. -->
so that a default instance of Main will be automatically constructed by the
container:
public Main() throws IOException {
this(RunMode.SERVLET);
}
There is a MainServlet class (only used in mode #3) whose job is to produce
the (singleton) MainComponent:
@Override protected MainComponent createComponent() {
return mainComponentProvider.get(); // this provider is injected by
Guice
}
For modes #1 and #2, Main has a standard main method:
public static void main(String... args) throws IOException {
new Main(RunMode.STANDALONE).getInjector();
}
It calls getInjector explicitly -- unlike mode #3, where it's done
implicitly thanks to GuiceServletContextListener.
Main also takes care of reading system properties and fixed properties files
to provide values for some important bind-time constants.
The actual operation of the program is controlled by a Guava Service,
MainService. For modes #1 and #2, the service is started automatically at
injection time, i.e., triggered by getInjector:
@Inject protected void startIfStandalone(MainService service) {
if (runMode == RunMode.STANDALONE) {
service.startStandalone();
}
}
For mode #3, it is started via the servlet context listener method:
@Override public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
// Starts a new thread and returns immediately.
service.start();
}
(There are corresponding techniques for dealing with shutdown. There's some
trickiness to handling shutdown hooks.)
MainService is responsible for starting and stopping various system-lifetime
services, in our case a cloud container context, a distributed node
discovery service, and a distributed data structure lifecycle service. More
pertinently to your question, it also starts and stops MainComponent, which
is where the Restlet machinery takes over.
--tim
On Tue, May 24, 2011 at 6:56 AM, Fabian Mandelbaum <[email protected]>wrote:
> Hello there,
>
> I'd like to have the same Restlet application deployed on different
> scenarios:
>
> 1) Standalone Java Application
> 2) Service/Daemon
> 3) Web Application Server (ex: Tomcat) contained
>
> Do I need to create three different projects? Or I "just" need to
> create three different "executable sets"?
>
> Is there any documentation to do this, with examples? I'm not talking
> about separate docs for each of 1,2,3 above, but a concrete
> documentation, if possible with examples, to do a restlet application
> that can be deployed on the above three scenarios "at the same time"
> (ok, with the needed modifs, but which are the "needed modifs"?)
>
> I hope to have been clear, thanks in advance for your answers.
>
> --
> Fabián Mandelbaum
> IS Engineer
>
> ------------------------------------------------------
>
> http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2746955
>
------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2746996