jetty-9 added a pretty welcome page

This commit is contained in:
Greg Wilkins 2012-10-12 15:36:32 +11:00
parent d173e91ef5
commit 6c011025b6
15 changed files with 513 additions and 68 deletions

View File

@ -16,9 +16,14 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet</artifactId>
<scope>provided</scope>
</dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -58,6 +58,7 @@ public class AbstractRestServlet extends HttpServlet
protected String _appid;
@Override
public void init(ServletConfig servletConfig) throws ServletException
{
if (servletConfig.getInitParameter(APPID_PARAM) == null)

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.example.asyncrest;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@ -31,8 +32,12 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.util.ajax.JSON;
/**
@ -53,12 +58,12 @@ public class AsyncRestServlet extends AbstractRestServlet
HttpClient _client;
@Override
public void init(ServletConfig servletConfig) throws ServletException
{
super.init(servletConfig);
_client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
@ -70,6 +75,7 @@ public class AsyncRestServlet extends AbstractRestServlet
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Long start=System.nanoTime();
@ -97,19 +103,21 @@ public class AsyncRestServlet extends AbstractRestServlet
// Send request each keyword
for (final String item:keywords)
{
_client.send(
new AsyncRestRequest(item)
_client.newRequest(restURL(item)).method(HttpMethod.GET).send(
new AsyncRestRequest()
{
@Override
void onAuctionFound(Map<String,String> auction)
{
void onAuctionFound(Map<String,String> auction)
{
resultsQueue.add(auction);
}
void onComplete()
{
if (outstanding.decrementAndGet()<=0)
async.dispatch();
}
});
resultsQueue.add(auction);
}
@Override
void onComplete()
{
if (outstanding.decrementAndGet()<=0)
async.dispatch();
}
});
}
// save timing info and return
@ -155,54 +163,63 @@ public class AsyncRestServlet extends AbstractRestServlet
out.close();
}
private abstract class AsyncRestRequest extends ContentExchange
private abstract class AsyncRestRequest implements Response.Listener
{
AsyncRestRequest(final String item)
{
// send the exchange
setMethod("GET");
setURL(restURL(item));
final Utf8StringBuilder _content = new Utf8StringBuilder();
AsyncRestRequest()
{
}
abstract void onAuctionFound(Map<String,String> details);
abstract void onComplete();
protected void onResponseComplete() throws IOException
@Override
public void onBegin(Response response)
{
}
@Override
public void onHeaders(Response response)
{
}
@Override
public void onContent(Response response, ByteBuffer content)
{
byte[] bytes = BufferUtil.toArray(content);
_content.append(bytes,0,bytes.length);
}
@Override
public void onSuccess(Response response)
{
}
@Override
public void onFailure(Response response, Throwable failure)
{
}
@Override
public void onComplete(Result result)
{
// extract auctions from the results
Map<String,?> query = (Map<String,?>) JSON.parse(this.getResponseContent());
Map<String,?> query = (Map<String,?>) JSON.parse(_content.toString());
Object[] auctions = (Object[]) query.get("Item");
if (auctions != null)
{
for (Object o : auctions)
onAuctionFound((Map<String,String>)o);
}
onComplete();
}
/* ------------------------------------------------------------ */
protected void onConnectionFailed(Throwable ex)
{
getServletContext().log("onConnectionFailed: ",ex);
onComplete();
}
abstract void onAuctionFound(Map<String,String> details);
abstract void onComplete();
};
/* ------------------------------------------------------------ */
protected void onException(Throwable ex)
{
getServletContext().log("onConnectionFailed: ",ex);
onComplete();
}
/* ------------------------------------------------------------ */
protected void onExpire()
{
getServletContext().log("onConnectionFailed: expired");
onComplete();
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!--
This is the jetty specific web application configuration file. When starting
a Web Application, the WEB-INF/jetty-web.xml file is looked for and if found, treated
as a org.eclipse.jetty.server.server.xml.XmlConfiguration file and is applied to the
org.eclipse.jetty.servlet.WebApplicationContext object
-->
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Get class="org.eclipse.jetty.util.log.Log" name="rootLogger">
<Call name="warn"><Arg>async-rest webapp is deployed. DO NOT USE IN PRODUCTION!</Arg></Call>
</Get>
</Configure>

View File

@ -10,7 +10,7 @@
<p>
This demo calls the EBay WS API both synchronously and asynchronously,
to obtain items matching each of the keywords passed on the query
string. The time the request thread is head is displayed for both.
string. The time the request thread is held by the servlet is displayed in red for both.
</p>
<table width='100%'>
@ -34,5 +34,11 @@ string. The time the request thread is head is displayed for both.
</tr>
</table>
By the use of Asynchronous Servlets and the Jetty Asychronous client, the server is able to release the thread (green) while
waiting for the response from Ebay. This thread goes back into the thread pool and can service many other requests during the wait.
This greatly reduces the number of threads needed, which in turn greatly reduces the memory requirements of the server.
<p>
Press reload to see even better results after JIT and TCP/IP warmup!
</body>
</html>

View File

@ -18,9 +18,7 @@
package org.eclipse.jetty.example.asyncrest;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;
public class DemoServer
@ -30,16 +28,13 @@ public class DemoServer
{
String jetty_home = System.getProperty("jetty.home",".");
Server server = new Server();
Connector connector=new SelectChannelConnector();
connector.setPort(Integer.getInteger("jetty.port",8080).intValue());
server.setConnectors(new Connector[]{connector});
Server server = new Server(Integer.getInteger("jetty.port",8080).intValue());
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setWar(jetty_home+"/target/example-async-rest-webapp-8.0.0.M0-SNAPSHOT");
webapp.setWar(jetty_home+"/target/async-rest/");
webapp.setParentLoaderPriority(true);
webapp.setServerClasses(new String[]{});
server.setHandler(webapp);
server.start();

View File

@ -77,15 +77,15 @@ import org.eclipse.jetty.util.thread.TimerScheduler;
* <p>Typical usage:</p>
* <pre>
* // One liner:
* new HTTPClient().GET("http://localhost:8080/").get().status();
* new HttpClient().GET("http://localhost:8080/").get().status();
*
* // Building a request with a timeout
* HTTPClient client = new HTTPClient();
* HttpClient client = new HttpClient();
* Response response = client.newRequest("http://localhost:8080").send().get(5, TimeUnit.SECONDS);
* int status = response.status();
*
* // Asynchronously
* HTTPClient client = new HTTPClient();
* HttpClient client = new HttpClient();
* client.newRequest("http://localhost:8080").send(new Response.Listener.Adapter()
* {
* &#64;Override

View File

@ -103,7 +103,7 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
throw new IllegalArgumentException("Invalid request scheme " + request.scheme() + " for destination " + this);
if (!host.equals(request.host()))
throw new IllegalArgumentException("Invalid request host " + request.host() + " for destination " + this);
if (port != request.port())
if (request.port()>0 && port != request.port())
throw new IllegalArgumentException("Invalid request port " + request.port() + " for destination " + this);
RequestPair requestPair = new RequestPair(request, listener);

View File

@ -102,6 +102,16 @@
<outputDirectory>${assembly-directory}/webapps</outputDirectory>
<destFileName>test.war</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
<artifactId>example-async-rest-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/webapps</outputDirectory>
<destFileName>async-rest.war</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-start</artifactId>
@ -495,6 +505,12 @@
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
<artifactId>example-async-rest-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
</profile>
</profiles>

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,55 @@
<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">
<head>
<META http-equiv="Pragma" content="no-cache">
<META http-equiv="Cache-Control" content="no-cache,no-store">
<META HTTP-EQUIV="Content-Script-Type" CONTENT="text/javascript">
<title>Welcome to Jetty-9</title>
<style type="text/css" title="jetty">
@import url(jetty.css);
</style>
</head>
<body>
<div id="header"></div>
<div id="content">
<h1>Welcome to Jetty 9</h1>
<p>
The Jetty project is a 100% Java <a href="http://en.wikipedia.org/wiki/Java_Servlet">Servlet</a> Container which supports asynchronous server and client implementations of the <a href="http://en.wikipedia.org/wiki/HTTP">HTTP</a>, <a href="http://en.wikipedia.org/wiki/WebSocket">Websocket</a> and <a href="http://en.wikipedia.org/wiki/SPDY">SPDY</a> protocols.
The project is 100% <a href="http://en.wikipedia.org/wiki/Open_source">Open Source</a> and hosted by the <a href="http://www.eclipse.org">Eclipse Foundation</a> at <a href="http://www.eclipse.org/jetty/">http://www.eclipse.org/jetty</a>.
</p>
</div>
<div id="links">
<table>
<tr>
<td>
<h2>examples ...</h2>
<ul>
<li><a href="/test/">Test Jetty Webapp</a></li>
<li><a href="/async-rest/">Async Rest</a></li>
<li><a href="http://docs.codehaus.org/display/JETTY/Jetty+Powered">Jetty Powered</a></li>
</ul>
</td>
<td>
<h2>information ... </h2>
<ul>
<li><a href="http://www.eclipse.org/jetty/">Jetty @ Eclipse Home</a></li>
<li><a href="http://wiki.eclipse.org/Jetty">Jetty @ Eclipse Doco</a></li>
</ul>
</td>
<td>
<h2>getting&nbsp;help ...</h2>
<ul>
<li><a href="http://www.eclipse.org/jetty/mailinglists.php">Mailing lists @ eclipse</a></li>
<li><a href="http://www.webtide.com/support.jsp">Webtide support</a></li>
<li><a href="http://www.webtide.com/training.jsp">Webtide training</a></li>
<li><a href="http://www.webtide.com/development.jsp">Webtide development</a></li>
</ul>
</td>
</tr>
</table>
</div>
</body>
</html>

View File

@ -0,0 +1,335 @@
BODY
{
font-family: Arial, Helvetica, sans-serif;
background-color: #FFFFFF;
font-size: 10pt;
}
img
{
border: 0px;
}
div#links table
{
width: 850px;
}
div#links td
{
vertical-align: top;
text-align: left;
border: 2px dotted #cccccc;
padding: 8px;
background-color: #efefef;
width: 280px;
}
div#links
{
margin-top: 20px;
width: 850px;
color: #999999;
margin-left: auto;
margin-right: auto;
}
div#links h1,h2,p
{
font-size: 10pt;
font-family: sans-serif;
text-align:left;
margin: 5px;
}
div#links h1
{
font-size: 22pt;
font-weight: normal;
font-family: sans-serif;
letter-spacing: 6pt;
color: #666666;
text-align: center;
margin-top:20px;
}
div#links h2
{
font-size: 12pt;
font-weight: normal;
letter-spacing: 2pt;
color: #666666;
}
div#header
{
clear: both;
background-image: url('images/jetty-header.jpg');
background-repeat: no-repeat;
background-position: center;
height:200px;
border-bottom: 3px ridge #cccccc;
border-right: 3px ridge #cccccc;
border-top: 3px groove #cccccc;
border-left: 3px groove #cccccc;
width: 850px;
margin-left: auto;
margin-right: auto;
}
div#content
{
clear: both;
font-size: 10pt;
font-weight: normal;
color: #666666;
margin-top: 30px;
width: 850px;
margin-left: auto;
margin-right: auto;
}
div#content h1
{
font-size: 14pt;
text-align:center;
}
div#footer
{
clear: both;
border-top: 4px groove #cccccc;
margin-top:20px;
padding-top:10px;
width: 850px;
}
A:link
{
color: #0099cc;
text-decoration: none;
font-weight: normal;
font-size: 10pt;
font-family:sans-serif;
}
A:visited
{
color: #0099cc;
text-decoration: none;
font-weight: normal;
font-size: 10pt;
font-family:sans-serif;
}
A:hover
{
color: #ff6600;
text-decoration: none;
font-weight: normal;
font-size: 10pt;
font-family:sans-serif;
}
A:active
{
color: #0099cc;
text-decoration: none;
font-weight: normal;
font-size: 10pt;
font-family:sans-serif;
}
A.disabled
{
color: #666666;
}
form
{
display: inline;
}
.SEVERE
{
background-color: #ff0000;
}
.WARNING
{
background-color: #ff6633;
}
.INFO
{
background-color: #00cc33;
}
.CONFIG
{
background-color: #999999;
}
.FINE
{
background-color: #3333ff;
}
.FINER
{
background-color: #3333cc;
}
.FINEST
{
background-color: #333399;
}
table
{
width: 100%;
border-spacing: 0px;
border-collapse: separate;
}
td
{
font-family: Arial,sans-serif;
font-size: 10pt;
padding: 2px;
margin: 0px;
border: #eeeeee groove 2px;
}
#content td
{
vertical-align: top;
}
#key
{
border-spacing: 0px;
border: 0px;
}
#key td
{
border: #eeeeee groove 2px;
font-size: 8pt;
font-family: Helvetica;
font-weight: bold;
color: white;
}
thead th
{
border: #eeeeee groove 2px;
}
.seq
{
width: 7em;
min-width: 7em;
max-width: 7em;
color: white;
font-family: Helvetica;
font-weight: bold;
}
.date
{
width: 19em;
min-width: 19em;
max-width: 19em;
color: black;
background-color: #eeeeee;
}
.thread
{
width: 3em;
min-width: 3em;
max-width: 3em;
color: black;
background-color: #eeeeee;
}
.logger
{
width: 30em;
min-width: 30em;
max-width: 30em;
background-color: #eeeeee;
}
.logclass
{
width: 30em;
min-width: 30em;
max-width: 30em;
background-color: #eeeeee;
}
.method
{
width: 20em;
min-width: 20em;
max-width: 20em;
background-color: #eeeeee;
}
.message
{
width: 250em;
min-width: 250em;
max-width: 250em;
text-align: left;
background-color: #eeeeee;
font-family: monospace;
}
.message table
{
border: 0px;
}
.message td,tr
{
text-align: left;
vertical-align: top;
padding-top: 0px;
border: 0px;
}
.except
{
background: #eeeeee;
padding-top: 2px;
}
.excepticon
{
width: 40px;
max-width: 40px;
min-width: 40px;
}
button
{
background: white;
}

View File

@ -410,6 +410,7 @@
<module>jetty-client</module>
<module>jetty-osgi</module>
<module>example-async-rest</module>
<!-- modules that need fixed and added back, or simply dropped and not maintained
<module>jetty-runner</module>
@ -426,7 +427,6 @@
<module>jetty-http-spi</module>
<module>test-jetty-nested</module>
<module>test-jetty-servlet</module>
<module>example-async-rest</module>
<module>tests</module>
-->
</modules>

View File

@ -19,7 +19,7 @@ detected.
<!-- + contextPath -->
<!-- + war OR resourceBase -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<Set name="contextPath">/</Set>
<Set name="contextPath">/test</Set>
<Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/test.war</Set>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->