For my unit-tests I use a simple test-server based on Jetty:
package eu.kostia.textanalysis.webservices.jetty;
import java.awt.Desktop;
import java.net.URI;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
public class TestServer {
static private final String CONTEXT_PATH = "/webservice";
static private final String PROJECT_HOME = System.getenv("MY_WORKSPACE_HOME") + "/WebServices";
static public final int PORT = 8080;
private Server server;
private Exception startException;
private static class SingletonHolder {
private static final TestServer INSTANCE = new TestServer();
}
/**
* Returns the singleton instance of the test server.
*
* @return the singleton instance of the test server.
*/
public static TestServer getInstance() {
return SingletonHolder.INSTANCE;
}
private TestServer() {
server = new Server(PORT);
WebAppContext context = new WebAppContext();
context.setDescriptor(PROJECT_HOME + "/web/WEB-INF/web.xml");
context.setResourceBase(PROJECT_HOME + "/web");
context.setContextPath(CONTEXT_PATH);
context.setParentLoaderPriority(true);
server.setHandler(context);
}
/**
* Start the test server. This method returns only when the server is
* complete started. There is no effect when you invoke this method and the
* server is already running.
*/
public void start() {
if (!server.isRunning()) {
startException = null;
new Thread("TestServer") {
public void run() {
try {
server.start();
server.join();
} catch (Exception exc) {
startException = exc;
}
}
}.start();
while (true) {
if (startException != null) {
throw new Error(startException);
}
// Block this method call until the server is started
if (server.isStarted()) {
return;
}
}
}
}
/**
* Stop the test server.
*/
public void stop() {
try {
if (server.isRunning()) {
server.stop();
}
} catch (Exception e) {
throw new Error(e);
}
}
/**
* Returns {@code true} is the server is running.
*
* @return {@code true} is the server is running.
*/
public boolean isRunning() {
return server.isRunning();
}
public static void main(String[] args) throws Exception {
TestServer.getInstance().start();
Desktop.getDesktop().browse(new URI("http://localhost:8080/webservice/"));
}
}
It works very well for servlet configured in web.xml but I'd now like to use the new annotation syntax introduced by the Servlet Specification 3.0, for example:
@WebServlet(urlPatterns = {"/hello"})
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter writer = response.getWriter();
writer.print("<h1>HttpServlet using Servlet 3.0</h1>");
}
}
How shoud I configure Jetty in my TestServer class to process also annotation-based servlets?
Add to your code
context.setConfigurations(new Configuration[] {
new AnnotationConfiguration(), new WebXmlConfiguration(),
new WebInfConfiguration(), new TagLibConfiguration(),
new PlusConfiguration(), new MetaInfConfiguration(),
new FragmentConfiguration(), new EnvConfiguration() });
You only need to set the AnnotationConfiguration to get the auto-discovery of annotated classes to work. The rest of the configurations are so you can enable other aspects of the container. Supposedly you should be able to do this from the commandline, using OPTIONS=annotations,jsp,(etc...), but I never got that working. At least this way it should pick up your annotated classes properly in the embedded environment.
Also as a side note it appears the Eclipse jetty project has annotation turned off by default, whereas riptide claims to have them turned on by default. I'm guessing this is a difference in the configuration files.