Embedding Tomcat and issuing requests to the deployed application
OK, I'm completely stuck. I want to run Tomcat in embedded mode so I can test an application without running the server in a separate process. I'm missing something simple, stupid, and important, and I need your help to see it.
This test fails with an HTTP error 400, Bad Request. I've tried MemoryProtocolHandler, context.invoke(), ... I don't know what to do. Maybe you see something simple.
package ca.jbrains.jsfunit.learning.test; import org.apache.catalina.Container; import org.apache.catalina.Context; import org.apache.catalina.Engine; import org.apache.catalina.connector.Connector; import org.apache.catalina.connector.Request; import org.apache.catalina.realm.MemoryRealm; import org.apache.catalina.startup.Embedded; import org.junit.After; import org.junit.Test; import com.gargoylesoftware.htmlunit.WebClient; public class LearnEmbeddedTomcatTest { private Embedded embedded; private Container host; private Engine engine; @Test public void deploySampleApplicationFromFileSystem() throws Exception { String tomcatPath = "/Users/jbrains/ThirdParty/apache-tomcat-5.5.28-embed"; // Create an embedded server embedded = new Embedded(); embedded.setCatalinaHome(tomcatPath); embedded.setRealm(new MemoryRealm()); // Create an engine engine = embedded.createEngine(); engine.setDefaultHost("localhost"); // Create a default virtual host host = embedded.createHost("localhost", tomcatPath + "/webapps"); engine.addChild(host); // 开发者_如何学GoCreate an application context Context context = embedded.createContext("TddJsfWeb", tomcatPath + "/webapps/TddJsfWeb"); host.addChild(context); // Install the assembled container hierarchy embedded.addEngine(engine); // Assemble and install a default HTTP connector Connector connector = embedded.createConnector("localhost", 8080, "http"); embedded.addConnector(connector); // Start the embedded server embedded.setAwait(true); embedded.start(); WebClient webClient = new WebClient(); webClient.getPage("http://localhost:8080/TddJsfWeb/static.xhtml"); } }
The unpacked .war is definitely at /Users/jbrains/ThirdParty/apache-tomcat-5.5.28-embed/webapps/TddJsfWeb/...
and static.xhtml
is in the root of the unpacked .war folder.
Please, please, show me how stupid I am. Thanks.
I had a similar experience with Tomcat. I ended up using Jetty instead - was a lot simpler to manage from a code point of view.
I'd like to second Jetty over Tomcat for this.. To run Jetty all I need is:
import java.awt.Desktop;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.bio.SocketConnector;
import org.mortbay.jetty.webapp.WebAppContext;
public class StartJetty {
public static void main(String[] args) throws Exception {
Server server = new Server();
SocketConnector connector = new SocketConnector();
// Set some timeout options to make debugging easier.
connector.setMaxIdleTime(1000 * 60 * 60);
connector.setSoLingerTime(-1);
connector.setPort(8081);
server.setConnectors(new Connector[] { connector });
WebAppContext bb = new WebAppContext();
bb.setServer(server);
bb.setContextPath("/");
bb.setWar("src/main/webapp");
server.addHandler(bb);
try {
System.out.println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY
KEY TO STOP");
server.start();
//Launch browser
if (Desktop.isDesktopSupported())
if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE))
try {
Desktop.getDesktop().browse(new URI("http://localhost:8081/"));
}
catch (IOException ioe) {
ioe.printStackTrace();
}
catch (URISyntaxException use) {
use.printStackTrace();
}
System.in.read();
System.out.println(">>> STOPPING EMBEDDED JETTY SERVER");
server.stop();
server.join();
}
catch (Exception e) {
e.printStackTrace();
System.exit(100);
}
}
}
If Jetty is working well for you then that is awesome, but if you want to dig a little deeper into Tomcat you can walk through your apps before you issue your request and see if they are available.
A third option is to look into a much simpiler container than Tomcat or Jetty, such as Winstone: http://winstone.sourceforge.net/
for (Container cont : host.findChildren()) {
if (cont instanceof StandardContext) {
StandardContext ctx = (StandardContext) cont;
ServletContext servletContext = ctx.getServletContext();
log.debug("Context initialized: {}", servletContext.getContextPath());
String prefix = servletContext.getRealPath("/");
try {
if (ctx.resourcesStart()) {
log.debug("Resources started");
}
log.debug("Context - available: {} privileged: {}, start time: {}, reloadable: {}", new Object[] { ctx.getAvailable(), ctx.getPrivileged(), ctx.getStartTime(), ctx.getReloadable() });
...
精彩评论