Separates the stock sample into "desktop" and "mobile" versions. Makes some
other not-quite-perfect changes to sxs-tree layout.
Review at http://gwt-code-reviews.appspot.com/276801
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7795 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java b/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java
index 114ebfe..04f0eb0 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeNodeView.java
@@ -22,6 +22,7 @@
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.ui.RequiresResize;
import java.util.List;
@@ -32,8 +33,6 @@
*/
public class SideBySideTreeNodeView<T> extends TreeNodeView<T> {
- private int columnHeight;
-
private int columnWidth;
private final int imageLeft;
@@ -53,13 +52,12 @@
*/
SideBySideTreeNodeView(final TreeView tree, final SideBySideTreeNodeView<?> parent,
NodeInfo<T> parentNodeInfo, Element elem, T value, int level, String path,
- int columnWidth, int columnHeight) {
+ int columnWidth) {
super(tree, parent, parentNodeInfo, value);
this.imageLeft = columnWidth - 16 - tree.getImageWidth();
this.level = level;
this.path = path;
this.columnWidth = columnWidth;
- this.columnHeight = columnHeight;
setElement(elem);
}
@@ -68,7 +66,7 @@
protected <C> TreeNodeView<C> createTreeNodeView(NodeInfo<C> nodeInfo,
Element childElem, C childValue, Void viewData, int idx) {
return new SideBySideTreeNodeView<C>(getTree(), this, nodeInfo, childElem,
- childValue, level + 1, path + "-" + idx, columnWidth, columnHeight);
+ childValue, level + 1, path + "-" + idx, columnWidth);
}
@Override
@@ -119,6 +117,13 @@
setChildContainer(animFrame.appendChild(Document.get().createDivElement()));
}
+ // TODO(jgw): Kind of a hack. We should probably be propagating onResize()
+ // down from the TreeView, but this is simpler for the moment.
+ TreeView tree = getTree();
+ if (tree instanceof RequiresResize) {
+ ((RequiresResize) tree).onResize();
+ }
+
return getChildContainer();
}
@@ -195,7 +200,6 @@
style.setTop(0, Unit.PX);
style.setLeft(level * columnWidth, Unit.PX);
style.setWidth(columnWidth, Unit.PX);
- style.setHeight(columnHeight, Unit.PX);
childCount++;
}
diff --git a/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeView.java b/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeView.java
index 57f42e8..0a6616c 100644
--- a/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeView.java
+++ b/bikeshed/src/com/google/gwt/bikeshed/tree/client/SideBySideTreeView.java
@@ -15,8 +15,11 @@
*/
package com.google.gwt.bikeshed.tree.client;
+import com.google.gwt.core.client.Scheduler;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.Node;
+import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
@@ -28,8 +31,6 @@
*/
public class SideBySideTreeView extends TreeView {
- protected int columnHeight = 200;
-
protected int columnWidth = 100;
/**
@@ -39,21 +40,18 @@
* @param viewModel the {@link TreeViewModel} that backs the tree
* @param rootValue the hidden root value of the tree
* @param columnWidth
- * @param columnHeight
*/
public <T> SideBySideTreeView(TreeViewModel viewModel, T rootValue,
- int columnWidth, int columnHeight) {
+ int columnWidth) {
super(viewModel);
this.columnWidth = columnWidth;
- this.columnHeight = columnHeight;
Element rootElement = Document.get().createDivElement();
rootElement.setClassName("gwt-sstree");
Style style = rootElement.getStyle();
style.setPosition(Position.RELATIVE);
style.setWidth(columnWidth, Unit.PX);
- style.setHeight(columnHeight, Unit.PX);
setElement(rootElement);
// Add event handlers.
@@ -61,7 +59,7 @@
// Associate a view with the item.
TreeNodeView<T> root = new SideBySideTreeNodeView<T>(this, null, null,
- rootElement, rootValue, 0, "gwt-sstree", columnWidth, columnHeight);
+ rootElement, rootValue, 0, "gwt-sstree", columnWidth);
setRootNode(root);
root.setState(true);
}
@@ -106,4 +104,27 @@
break;
}
}
+
+ public void onResize() {
+ if (!isAttached()) {
+ return;
+ }
+
+ int height = getElement().getOffsetHeight();
+ NodeList<Node> children = getElement().getChildNodes();
+ for (int i = 0; i < children.getLength(); ++i) {
+ Element child = children.getItem(i).cast();
+ child.getStyle().setHeight(height, Unit.PX);
+ }
+ }
+
+ @Override
+ protected void onLoad() {
+ // TODO(jgw): This is a total hack.
+ Scheduler.get().scheduleFinally(new Scheduler.ScheduledCommand() {
+ public void execute() {
+ onResize();
+ }
+ });
+ }
}
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StockSample.gwt.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksCommon.gwt.xml
similarity index 60%
rename from bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StockSample.gwt.xml
rename to bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksCommon.gwt.xml
index c3c3ef4..c69470f 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StockSample.gwt.xml
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksCommon.gwt.xml
@@ -1,16 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
-<module rename-to='stocks'>
- <!-- Inherit the core Web Toolkit stuff. -->
+<module>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.regexp.RegExp'/>
<inherits name='com.google.gwt.bikeshed.list.List'/>
<inherits name='com.google.gwt.bikeshed.tree.Tree'/>
- <!-- Specify the app entry point class. -->
- <entry-point class='com.google.gwt.sample.bikeshed.stocks.client.StockSample'/>
-
- <!-- Specify the paths for translatable code -->
<source path='client'/>
<source path='shared'/>
</module>
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksDesktop.gwt.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksDesktop.gwt.xml
new file mode 100644
index 0000000..6977c58
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksDesktop.gwt.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
+<module rename-to='stocksdesktop'>
+ <inherits name='com.google.gwt.sample.bikeshed.stocks.StocksCommon'/>
+ <entry-point class='com.google.gwt.sample.bikeshed.stocks.client.StocksDesktop'/>
+</module>
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksMobile.gwt.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksMobile.gwt.xml
new file mode 100644
index 0000000..c6cfbcd
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/StocksMobile.gwt.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
+<module rename-to='stocksmobile'>
+ <inherits name='com.google.gwt.sample.bikeshed.stocks.StocksCommon'/>
+ <entry-point class='com.google.gwt.sample.bikeshed.stocks.client.StocksMobile'/>
+</module>
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java
index cc8d61e..6e9b848 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/Columns.java
@@ -110,7 +110,7 @@
protected String getValue(Transaction object) {
int price = object.getActualPrice() * object.getQuantity();
return (object.isBuy() ? " (" : " ")
- + StockSample.getFormattedPrice(price) + (object.isBuy() ? ")" : "");
+ + StocksDesktop.getFormattedPrice(price) + (object.isBuy() ? ")" : "");
}
};
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/PlayerScoresWidget.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/PlayerScoresWidget.java
index 4c18352..ac55f44 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/PlayerScoresWidget.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/PlayerScoresWidget.java
@@ -48,9 +48,9 @@
sb.append("<b>Name: </b>");
sb.append(value.getDisplayName());
sb.append("<br><b>Net Worth: </b>");
- sb.append(StockSample.getFormattedPrice(value.getNetWorth()));
+ sb.append(StocksDesktop.getFormattedPrice(value.getNetWorth()));
sb.append("<br><b>Cash: </b>");
- sb.append(StockSample.getFormattedPrice(value.getCash()));
+ sb.append(StocksDesktop.getFormattedPrice(value.getCash()));
List<String> status = value.getStatus();
if (status != null) {
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockSample.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksDesktop.java
similarity index 98%
rename from bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockSample.java
rename to bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksDesktop.java
index 2aad2f7..4071b5b 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockSample.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksDesktop.java
@@ -51,9 +51,9 @@
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
-public class StockSample implements EntryPoint, Updater {
+public class StocksDesktop implements EntryPoint, Updater {
- interface Binder extends UiBinder<Widget, StockSample> { }
+ interface Binder extends UiBinder<Widget, StocksDesktop> { }
private static final Binder binder = GWT.create(Binder.class);
@@ -333,7 +333,7 @@
@UiFactory
SideBySideTreeView createTransactionTree() {
- return new SideBySideTreeView(treeModel, null, 200, 200);
+ return new SideBySideTreeView(treeModel, null, 200);
}
// Hack - walk the transaction tree to find the current viewed sector
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockSample.ui.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksDesktop.ui.xml
similarity index 90%
rename from bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockSample.ui.xml
rename to bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksDesktop.ui.xml
index 77670d2..9742448 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StockSample.ui.xml
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksDesktop.ui.xml
@@ -31,9 +31,11 @@
</g:west>
<g:north size="18">
- <g:ScrollPanel styleName='{common.bg}'>
- <t:SideBySideTreeView ui:field='transactionTree'/>
- </g:ScrollPanel>
+ <g:LayoutPanel styleName='{common.bg}'>
+ <g:layer>
+ <t:SideBySideTreeView ui:field='transactionTree'/>
+ </g:layer>
+ </g:LayoutPanel>
</g:north>
<g:center>
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.java
new file mode 100644
index 0000000..cca8651
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.java
@@ -0,0 +1,146 @@
+package com.google.gwt.sample.bikeshed.stocks.client;
+
+import com.google.gwt.bikeshed.list.client.PagingTableListView;
+import com.google.gwt.bikeshed.list.client.TextHeader;
+import com.google.gwt.bikeshed.list.shared.AsyncListModel;
+import com.google.gwt.bikeshed.list.shared.Range;
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.sample.bikeshed.stocks.shared.StockQuote;
+import com.google.gwt.sample.bikeshed.stocks.shared.StockQuoteList;
+import com.google.gwt.sample.bikeshed.stocks.shared.StockRequest;
+import com.google.gwt.sample.bikeshed.stocks.shared.StockResponse;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiFactory;
+import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.Widget;
+
+public class StocksMobile {
+
+ interface Binder extends UiBinder<Widget, StocksMobile> {}
+ private static final Binder binder = GWT.create(Binder.class);
+
+ /**
+ * The delay between updates in milliseconds.
+ */
+ private static final int UPDATE_DELAY = 5000;
+
+ static String getFormattedPrice(int price) {
+ return NumberFormat.getCurrencyFormat("USD").format(price / 100.0);
+ }
+
+ @UiField PagingTableListView<StockQuote> listView;
+ private final StockServiceAsync dataService = GWT.create(StockService.class);
+ private AsyncListModel<StockQuote> favoritesListModel;
+
+ /**
+ * The timer used to update the stock quotes.
+ */
+ private Timer updateTimer = new Timer() {
+ @Override
+ public void run() {
+ update();
+ }
+ };
+
+ /**
+ * This is the entry point method.
+ */
+ public void onModuleLoad() {
+ // Create the various models. Do this before binding the UI, because some
+ // of the UiFactories need the models to instantiate their widgets.
+ favoritesListModel = new AsyncListModel<StockQuote>() {
+ @Override
+ protected void onRangeChanged(int start, int length) {
+ update();
+ }
+ };
+
+ // Now create the UI.
+ RootPanel.get().add(binder.createAndBindUi(this));
+ update();
+ }
+
+ /**
+ * Process the {@link StockResponse} from the server.
+ *
+ * @param response the stock response
+ */
+ public void processStockResponse(StockResponse response) {
+ // Update the favorites list.
+ updateFavorites(response);
+
+ // Restart the update timer.
+ updateTimer.schedule(UPDATE_DELAY);
+ }
+
+ public void update() {
+ Range[] favoritesRanges = favoritesListModel.getRanges();
+
+ StockRequest request = new StockRequest("TODO", null, null,
+ favoritesRanges[0], null);
+
+ dataService.getStockQuotes(request, new AsyncCallback<StockResponse>() {
+ public void onFailure(Throwable caught) {
+ if (handleRpcError(caught, null)) {
+ updateTimer.schedule(UPDATE_DELAY);
+ }
+ }
+
+ public void onSuccess(StockResponse result) {
+ processStockResponse(result);
+ }
+ });
+ }
+
+ @UiFactory
+ PagingTableListView<StockQuote> createFavoritesWidget() {
+ PagingTableListView<StockQuote> listView = new PagingTableListView<StockQuote>(
+ favoritesListModel, 10);
+
+ listView.addColumn(Columns.tickerColumn, new TextHeader("ticker"));
+ listView.addColumn(Columns.priceColumn, new TextHeader("price"));
+ listView.addColumn(Columns.changeColumn, new TextHeader("change"));
+ listView.addColumn(Columns.sharesColumn, new TextHeader("shares"));
+ listView.addColumn(Columns.dollarsColumn, new TextHeader("value"));
+ listView.addColumn(Columns.profitLossColumn, new TextHeader("profit/loss"));
+
+ return listView;
+ }
+
+ /**
+ * Display a message to the user when an RPC call fails.
+ *
+ * @param caught the exception
+ * @param displayMessage the message to display to the user, or null to
+ * display a default message
+ * @return true if recoverable, false if not
+ */
+ private boolean handleRpcError(Throwable caught, String displayMessage) {
+ String message = caught.getMessage();
+ if (message.contains("Not logged in")) {
+ // Force the user to login.
+ Window.Location.reload();
+ return false;
+ }
+
+ if (displayMessage == null) {
+ displayMessage = "ERROR: " + caught.getMessage();
+ }
+ Window.alert(displayMessage);
+ return true;
+ }
+
+ private void updateFavorites(StockResponse response) {
+ // Update the favorites list.
+ StockQuoteList favorites = response.getFavorites();
+ favoritesListModel.updateDataSize(response.getNumFavorites(), true);
+ favoritesListModel.updateViewData(favorites.getStartIndex(),
+ favorites.size(), favorites);
+ }
+}
+
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.ui.xml b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.ui.xml
new file mode 100644
index 0000000..1c7ee0c
--- /dev/null
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/client/StocksMobile.ui.xml
@@ -0,0 +1,14 @@
+<ui:UiBinder
+ xmlns:ui='urn:ui:com.google.gwt.uibinder'
+ xmlns:g='urn:import:com.google.gwt.user.client.ui'
+ xmlns:l='urn:import:com.google.gwt.bikeshed.list.client'
+ xmlns:t='urn:import:com.google.gwt.bikeshed.tree.client'
+ xmlns:s='urn:import:com.google.gwt.sample.bikeshed.stocks.client'>
+
+ <ui:style field='common' src='common.css'/>
+
+ <g:HTMLPanel>
+ <div styleName='{common.header-left}'>Portfolio / Favorites</div>
+ <l:PagingTableListView ui:field='listView' styleName='{common.table}'/>
+ </g:HTMLPanel>
+</ui:UiBinder>
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/server/StockServiceImpl.java b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/server/StockServiceImpl.java
index ccaed91..74560cb 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/server/StockServiceImpl.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/stocks/server/StockServiceImpl.java
@@ -185,7 +185,8 @@
Range sectorRange = request.getSectorRange();
PlayerStatus player = ensurePlayer();
- Result searchResults = getSearchQuotes(query, searchRange);
+ Result searchResults = searchRange != null ?
+ getSearchQuotes(query, searchRange) : null;
Result favorites = queryFavorites(favoritesRange);
String sectorName = request.getSector();
Result sector = sectorRange != null ? getSectorQuotes(sectorName,
diff --git a/bikeshed/src/com/google/gwt/sample/bikeshed/tree/client/TreeSample.java b/bikeshed/src/com/google/gwt/sample/bikeshed/tree/client/TreeSample.java
index ce4a05e..1476fe8 100644
--- a/bikeshed/src/com/google/gwt/sample/bikeshed/tree/client/TreeSample.java
+++ b/bikeshed/src/com/google/gwt/sample/bikeshed/tree/client/TreeSample.java
@@ -32,8 +32,9 @@
RootPanel.get().add(tree);
RootPanel.get().add(new HTML("<hr>"));
-
- SideBySideTreeView sstree = new SideBySideTreeView(new MyTreeViewModel(), "...", 100, 200);
+
+ SideBySideTreeView sstree = new SideBySideTreeView(new MyTreeViewModel(), "...", 100);
+ sstree.setHeight("200px");
RootPanel.get().add(sstree);
}
}
diff --git a/bikeshed/war/Stocks.html b/bikeshed/war/Stocks.html
index 0b3e56c..85c4b5d 100644
--- a/bikeshed/war/Stocks.html
+++ b/bikeshed/war/Stocks.html
@@ -4,7 +4,7 @@
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="Stocks.css">
<title>Stock Game Sample</title>
- <script type="text/javascript" language="javascript" src="stocks/stocks.nocache.js"></script>
+ <script type="text/javascript" language="javascript" src="stocksdesktop/stocksdesktop.nocache.js"></script>
</head>
<body>
diff --git a/bikeshed/war/StocksMobile.html b/bikeshed/war/StocksMobile.html
new file mode 100644
index 0000000..442ed18
--- /dev/null
+++ b/bikeshed/war/StocksMobile.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <link type="text/css" rel="stylesheet" href="Stocks.css">
+ <title>Stock Game Sample</title>
+ <script type="text/javascript" language="javascript" src="stocksmobile/stocksmobile.nocache.js"></script>
+ </head>
+
+ <body>
+ <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
+ <noscript>
+ <div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
+ Your web browser must have JavaScript enabled
+ in order for this application to display correctly.
+ </div>
+ </noscript>
+ </body>
+</html>
diff --git a/bikeshed/war/WEB-INF/web.xml b/bikeshed/war/WEB-INF/web.xml
index 096e396..ad7251e 100644
--- a/bikeshed/war/WEB-INF/web.xml
+++ b/bikeshed/war/WEB-INF/web.xml
@@ -28,7 +28,12 @@
<servlet-mapping>
<servlet-name>stockServlet</servlet-name>
- <url-pattern>/stocks/stock</url-pattern>
+ <url-pattern>/stocksdesktop/stock</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>stockServlet</servlet-name>
+ <url-pattern>/stocksmobile/stock</url-pattern>
</servlet-mapping>
<servlet-mapping>