Cleanest Jetty Configuration for Development?
EDIT: I think I should clarify my intent...
I'm trying to simplify the development iteration cycle of write-code >> build WAR >> deploy >> refresh >> repeat. I'd like to be relatively independent of IDE (i.e., I don't want Eclipse or IntelliJ plug-ins doing the work). I want to be able to edit code/static files and build as needed into my WAR source directory, and just have run/debug setup as a command line call to a centralized Jetty installation.
Later I'd like to be able to perform the actual deployment using generally the same setup but with a packaged up WAR. I don't want to have my app code specific to my IDE or Jetty.
So perhaps a better way to ask this question is What have you found is the cleanest way to use Jetty as your dev/debug app server?
Say I want to have a minimal Jetty 7 installation. I want as minimal of XML configuration as possible, I just need the raw Servlet API, no JSP, no filtering, etc. I just want to be able to have some custom servlets and have static files served up if they exist. This will be the only WAR and it will sit as the root for a given port.
Ideally, for ease of deployment I'd like to have the Jetty directory just be the standard download, and my WAR / XML config be separate from these standard开发者_运维知识库 Jetty files. In my invocation of Jetty I'd like to pass in this minimal XML and go.
I'm finding that the documentation is all over the place and much of it is for Jetty 6 or specific to various other packages (Spring, etc.). I figure if I have this minimal configuration down then adding additional abstractions on top will be a lot cleaner. Also it will allow me to more cleanly deal with embedded-Jetty scenarios.
This SO question is an example scenario where this XML would be useful Jetty Run War Using only command line
What would be the minimal XML needed for specifying this one WAR location and the hosts/port to serve it?
Thanks in advance for any snippets or links.
Jetty has migrated to Eclipse. There is very subtle info on this. This also led in change in package name, which is another level of nuance. They did publish a util to convert Jetty6 setting to Jetty 7 setting, but again -- not very popular. I am dissapointed from Eclipse Jetty forum. Here is where you should look for documentation on Jetty 7 onwards http://wiki.eclipse.org/Jetty/Starting
I think this is the minimal jetty.xml
taken from http://wiki.eclipse.org/Jetty/Reference/jetty.xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">\
<Configure id="Server" class="org.eclipse.jetty.server.Server">
</Configure>
But, I would rather like to start from a copy of $JETTY_HOME/etc/jetty.xml
and would modify from there.
If you are Okay with $JETTY_HOME/webapps
directory, you can set up the port by modifying this part
<Configure id="Server" class="org.eclipse.jetty.server.Server">
...
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
<Set name="host"><Property name="jetty.host" /></Set>
<Set name="port"><Property name="jetty.port" default="7777"/></Set>
<Set name="maxIdleTime">300000</Set>
<Set name="Acceptors">2</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">20000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
</New>
</Arg>
</Call>
....
</Configure>
Else, I will modify context.xml
the way explained here (for Jetty 7) How to serve webbapp A from portA and webapp B from portB
Also refer these pages:
- http://wiki.eclipse.org/Jetty/Reference/jetty.xml
- http://wiki.eclipse.org/Jetty/Reference/jetty.xml_syntax
- http://communitymapbuilder.org/display/JETTY/JNDI
.... Edit#1: sorry for wrong URL for webapp per connector. I have updated the link to How to serve webbapp A from portA and webapp B from portB to point to the doc that is meant for Jetty 7.
Update on 'how you deal with Jetty on various environments?'
Dev
We use Maven, so embeded Jetty works for us. We just run mvn clean install run:jetty
and the port is configured in Maven's config file, namely pom.xml
. This is not IDE dependent plus Jetty can easily be embedded using ANT, but I never tried.
Test
We have stand-alone Jetty running. I've configured port and tuned parameters, removed default apps (e.g. root.war etc) and created a context.xml with app specific ports and deployment directory. (Unfortunately, I have asked this question on Eclipse Jetty's mailing list and no one bothered to answer). This is one time setting.
For test builds/deployments, we have a build script that builds the WAR as per test env specs and then uploads it to test environment. After, that we invoke a shell script that (1)stops Jetty, (2) copies war file to myApp's webapp direactory and (3) restarts Jetty.
However, easier way to do this is by using Maven's Cargo plugin. The bad luck was that I was using Jetty 7.1.6 which was incompatible with Cargo. Later they fixed it, but I had got my job done by custom script.
Prod
Prod has almost same procedure as test, except. The tunings are done for higher security and load-balancing. But from deployment POV, there is nothing different from Test case to Prod.
Notice that I have not bothered about what XML files are and how many must be there. I have just used the ones that are my concerns -- jetty.xml
and context.xml
. Plus, I found it's much cleaner to use jetty.conf
and jetty.sh
for passing JVM params, custom XMLs and for starting and stopping.
Hope this helps.
On hot deployment:
Now, if you use Maven and use embedded Jetty. It just knows when the code is changed -- like "gunshot sniffer". In dev envt, you run Jetty, make changes, refresh page, and see your changes -- hot deployment. Find more here http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin look for scanIntervalSeconds
This doesn't fully answer your question, but in case it helps, here's some pretty minimal code using embedded Jetty 7 to fire up a server with one root servlet:
HandlerCollection handlers = new HandlerCollection();
ServletContextHandler root = new ServletContextHandler(handlers, "/", ServletContextHandler.NO_SESSIONS|ServletContextHandler.NO_SECURITY);
root.addServlet(new ServletHolder(new MyServlet()), "/*");
Server server = new Server(8080);
server.setHandler(handlers);
server.start();
See of course http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty.
If you are building with maven (which is IDE independent) then you should debug with the maven jetty plugin. Basically you run the app as "mvn jetty:run" on the commandline it all just works without having to do any redeployment. Most good IDEs how have maven support built in and lets you run/debug the app as a maven; meaning that maven is run which starts the jetty plugin which starts the app and you can debug it. Since everything is running out of the IDE source and bin folders you don't even need a jetty server install.
Here is a demo project which runs that way https://github.com/simbo1905/ZkToDo2/blob/master/commandline.build.and.run.txt and here is how to run it under eclipse https://github.com/simbo1905/ZkToDo2/blob/master/eclipse.indigo.build.and.debug.txt but any IDE which understands maven should work. Take a look at the pom.xml where it sets up the maven jetty plugin.
I would use Gradle and scan the build output folder every few seconds for changes in the build.
In a build.gradle file:
apply plugin: 'jetty'
...
jettyRun.doFirst {
// set system properties, etc here for bootstrapping
}
jettyRun {
httpPort = 8989
reload = 'automatic'
scanIntervalSeconds = 3
daemon = false
}
That's it. You can choose to have the IDE auto-build for you, and point at that directory. But you can also choose not to. This solution is not tied at all to an IDE.
I thought I'd update with what I now do. I've written a tiny command line app / Maven archetype which works like how I thought this all should have in the first place. The bootstrap app lets you launch your servlet container of choice (Jetty, Tomcat, GlassFish) by just passing it the path to the WAR and your port.
Using Maven, you can create and package your own instance of this simple app:
mvn archetype:generate \
-DarchetypeGroupId=org.duelengine \
-DarchetypeArtifactId=war-bootstrap-archetype \
-DarchetypeVersion=0.2.1
Then you launch it like this:
java -jar bootstrap.jar -war myapp.war -p 8080 --jetty
Here's the source for the utility and the archetype: https://bitbucket.org/mckamey/war-bootstrap
精彩评论