writing JSPs to play chess; I get a null at a point, where I shouldn't
I am writing a set of JSP pages in order to play chess online. I know it is better to do this task using an applet, but the man I am working for doesn't want it to be an applet. The idea is two clients play a game, while in fact manipulating a single object in the application or ServletContext object. If one of the clients makes a move - he modifies the Game object and the thread (a loop checking if the Game object has changed), created by the other client stops and his _service method visualizes the move his opponent has made. As soon as a client submits a move - his _service method creates and join()s the thread waiting for the next change in the Game object.
MY PROBLEM IS: THE SECOND TIME THE HOST PLAYS A MOVE HIS OPPONENT GETS A NULL INSTEAD OF VALID Game OBJECT. CAN ANYONE TELL ME WHY BECAUSE I HAVEN'T SET IT TO NULL ANYWHERE IN THE CODE
I have the following files: chessOnline.jsp, hostGame.jsp, joinGame.jsp, play.jsp, quitGame.jsp and a few .class files: Game.class, MovesStateChecker and GameOnChecker.
chessOnline.jsp has two functions:
1. to join a created game
2. to create a new game
joinGame.jsp and hostGame.jsp are just like play.jsp with the difference that they initialize the game; the code is quite the same.
MovesStateChecker -
public class MovesStateChecker extends Thread
{
private ServletContext sc;
private int movesNumber;
public MovesStateChecker(String name,ServletContext sc,int movesNumber)
{
super(name);
this.movesNumber=movesNumber;
this.sc=sc;
}
public void run()
{
Game g=null;
int retries=0;
while(true)
{
try {
Thread.sleep(1500);
} catch (InterruptedException e) {}
g=(Game)sc.getAttribute(this.getName());
if(g==null){retries+=1;continue;}
if(g.getMoves().size()>movesNumber){break;}
}
}
}
end of MovesStateChecker.class
joinGame.jsp--
<%@ page contentType="text/html; charset=iso-8859-1" language="java" import="java.util.Map,java.io.IOException,chessoffice.*,java.sql.*" errorPage="" %>
<%
response.setHeader("Cache-Control","no-cache"); //Forces caches to obtain a new copy of the page from the origin server
response.setHeader("Cache-Control","no-store"); //Directs caches not to store the page under any circumstance
response.setDateHeader("Expires", 0); //Causes the proxy cache to see the page as "stale"
response.setHeader("Pragma","no-cache"); //HTTP 1.0 backward compatibility
%>
<html>
<head>
<link rel="stylesheet" href="styles.css" type="text/css" />
<title>Read</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<%
if (Strings.dbCheckSession(request))
{
String user =(String)session.getAttribute("sessionUser");
if(request.getParameter("gameId")==null || request.getParameter("gameId").equals(""))
{
response.sendRedirect(response.encodeURL("/jsp/chessOnline.jsp"));
}
else
{
Game joinedGame=(Game)application.getAttribute(request.getParameter("gameId"));
if(joinedGame.getBlack()==null)
{joinedGame.setBlack(user);}
else
{joinedGame.setWhite(user);}
joinedGame.setGameOn(true);
application.setAttribute(request.getParameter("gameId"),joinedGame);
MovesStateChecker msc=new MovesStateChecker(joinedGame.getId(),application,0);
msc.start();
msc.join();
Game g=(Game)application.getAttribute(request.getParameter("gameId"));
if(g==null)
{
response.sendRedirect(response.encodeURL("/jsp/chessOnline.jsp?error=opponentQuit"));
}
else
{
out.println(g.getWhite()+" - white player<br />");
out.println(g.getBlack()+" - black player<br />");
out.println(g.getMoves().size()+" - size of Moves array list (number of moves)<br />");
out.println(g.isGameOn()+ " - is the game on <br />");
out.println(g.getDesk().get("b2")+" - b2 position<br />");
out.println(g.getDesk().get("b4")+" - b4 position<br />--<br />");
out.println("<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">");
out.println("<tr><td>");
Read.drawDesk(false,g.getDesk(),out);
out.println("</td><td>");
Read.drawInfoForm(request.getParameter("gameId"),out);
out.println("</td></tr>");
out.println("</table><br /><hr />");
Read.drawQuitForm(request.getParameter("gameId"),out);
}
}
}
else response.sendRedirect(response.encodeURL("/jsp/index.jsp"));
%>
</body>
</html>
end of joinGame.jsp--
-hostGame.jsp-
<%@ page contentType="text/html; charset=iso-8859-1" language="java" import="java.io.IOException,chessoffice.*,java.util.*,java.sql.*" errorPage="" %>
<%!
public Map initGameMap() {
Map m=Collections.synchronizedMap(new HashMap(64,(float)0.1));
for(int ver=8;ver>=1;ver--){
for(int hor=0;hor<=7;hor++) {
switch(ver) {
case 1: m.put(""+Read.chars[hor]+ver,"white/"+Read.bfigs[hor]+".gif");break;
case 2: m.put(""+Read.chars[hor]+ver,"white/p.gif");break;
case 7: m.put(""+Read.chars[hor]+ver,"black/p.gif");break;
case 8: m.put(""+Read.chars[hor]+ver,"black/"+Read.bfigs[hor]+".gif");break;
default: m.put(""+Read.chars[hor]+ver,null);break;
}
}
}
return m;
}
%>
<%
response.setHeader("Cache-Control","no-cache"); //Forces caches to obtain a new copy of the page from the origin server
response.setHeader("Cache-Control","no-store"); //Directs caches not to store the page under any circumstance
response.setDateHeader("Expires", 0); //Causes the proxy cache to see the page as "stale"
response.setHeader("Pragma","no-cache"); //HTTP 1.0 backward compatibility
%>
<html>
<head>
<script language="JavaScript" type="text/javascript">
function selectFigure(cell)
{
/*oldPos=cell.name;
bgImage=cell.background;
document.write(bgImage.substring(0,bgImage.indexOf("."))+"_"+bgImage.substring(bgImage.indexOf(".")-1,bgImage.length()));
cell.background=bgImage.substring(0,bgImage.indexOf("."))+"_"+bgImage.substring(bgImage.indexOf(".")-1,bgImage.length());
*/
alert("cell name is: "+cell.background);
}
</script>
<title>chess online</title>
<link rel="stylesheet" href="styles.css" type="text/css" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<%
if (Strings.dbCheckSession(request))
{
String user=(String)session.getAttribute("sessionUser");
Game initialGame=new Game();
initialGame.setId(user);
if(request.getParameter("color")!=null)
{
if(request.getParameter("color").equals("white"))
{
initialGame.setWhite(user);
}
else
{
initialGame.setBlack(user);
}
}
else
{
initialGame.setWhite(user);
}
initialGame.setGameOn(false);
initialGame.setWhiteTime(10*60*1000);
initialGame.setBlackTime(10*60*1000);
initialGame.setMoves(new ArrayList());
initialGame.setDesk(this.initGameMap());
initialGame.setCaptured(new ArrayList());
application.setAttribute(initialGame.getId(),initialGame);
GameOnChecker goc=new GameOnChecker(initialGame.getId(),application);
goc.start();
goc.join();
Game g=(Game)application.getAttribute(user);
out.println(g.getWhite()+" - white player (host)<br />");
out.println(g.getBlack()+" - black player<br />");
out.println(g.getMoves().size()+" - size of Moves array list (number of moves)<br />");
out.println(g.isGameOn()+ " - is the game on<br />");
out.println(g.getDesk().get("b2")+" - b2 position<br />");
out.println(g.getDesk().get("b4")+" - b4 position<br />-<br />");
out.println("<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">");
out.println("<tr><td>");
Read.drawDesk(false,g.getDesk(),out);
out.println("</td><td>");
Read.drawInfoForm(user,out);
out.println("</td></tr>");
out.println("</table><br /><hr />");
Read.drawQuitForm(user,out);
}
else response.sendRedirect(response.encodeURL("/jsp/index.jsp"));
%>
</body>
</html>
-end of hostGame.jsp-
-play.jsp-
<%@ page contentType="text/html; charset=iso-8859-1" language="java" import="chessoffice.*,java.sql.*" errorPage="" %>
<%
response.setHeader("Cache-Control","no-cache"); //Forces caches to obtain a new copy of the page from the origin server
response.setHeader("Cache-Control","no-store"); //Directs caches not to store the page under any circumstance
response.setDateHeader("Expires", 0); //Causes the proxy cache to see the page as "stale"
response.setHeader("Pragma","no-cache"); //HTTP 1.0 backward compatibility
%>
<html>
<head>
<link rel="stylesheet" href="styles.css" type="text/css" />
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<%
boolean overtake=(request.getParameter("overtake").equals("true"))?true:false;
String bgImage=request.getParameter("bgImage");
String oldPos=request.getParameter("old");
String newPos=request.getParameter("new");
String gameId=request.getParameter("gameId");
if(newPos!=null && oldPos!=null && bgImage!=null && gameId!=null)
{
//tuk trqbva da ima proverka na hod-a
//posle se suzdava obekt ot tipa Move i se zapisva v Game.moves:
Move m=new Move(oldPos,newPos,overtake,bgImage);
Game loadedGame=(Game)application.getAttribute(gameId);
loadedGame.updateDesk(m);
int currentMovesNumber=loadedGame.getMoves().size();
application.setAttribute(gameId,loadedGame);
MovesStateChecker msc=new MovesStateChecker(loadedGame.getId(),application,currentMovesNumber);
msc.start();
msc.join();
Game g=(Game)application.getAttribute((String)session.getAttribute("sessionUser"));
if(g==null)
{
out.println("izvadenata igra e NULL");
//response.sendRedirect(response.encodeURL("/jsp/chessOnline.jsp?error=opponentQuit"));
}
else
{
out.println(g.getWhite()+" - white player<br />");
out.println(g.getBlack()+" - black player<br />");
out.println(g.getMoves().size()+" - size of Moves array list (number of moves)<br />");
out.println(g.isGameOn()+ " - is the game on <br />");
out.println(g.getDesk().get("b2")+" - b2 position<br />");
out.println(g.getDesk().get("b4")+" - b4 position<br />--<br />");
out.println("<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">");
out.println("<tr><td>");
Read.drawDesk(false,g.getDesk(),out);
out.println("</td><td>");
Read.drawInfoForm(request.getParameter("gameId"),out);
out.println("</td></tr>");
out.println("</table><br /><hr />");
Read.drawQuitForm(request.getParameter("gameId"),out);
}
}
%>
</body>
</html>
-play.jsp-
chessOnline.jsp-
<%@ page contentType="text/html; charset=iso-8859-1"language="java" import="java.util.*,java.io.*,chessoffice.*,java.sql.*" errorPage="" %>
<%!
public void drawJoinGameForm(javax.servlet.jsp.JspWriter out,ServletContext application) throws IOException
{
out.println("<form action=\"joinGame.jsp\" method=\"get\">");
out.println("<select style=\"width:300\" name=\"gameId\" size=\"6\" size=\"120\">");
Enumeration e=application.getAttributeNames();
while(e.hasMoreElements())
{
String el=(String)e.nextElement();
if(el.length()<=20 && ((Game)application.getAttribute(el)).isGameOn()==false)
out.println("<option value=\""+el+"\" >"+el+"</option>");
}
out.println("</select>");
out.println("<br /><input type=\"submit\" value=\"Join Game\" />");
out.println("</form>");
}
public void drawHostGameForm(javax.servlet.jsp.JspWriter out) throws IOException
{
out.println("<form action=\"hostGame.jsp\" method=\"get\" name=\"hostGameForm\">");
out.println("<input type=\"submit\" value=\"Host New Game\" />");
out.println("<br />Choose your color:<br />");
out.println("<input type=\"radio\" name=\"color\" value=\"white\" checked=\"checked\" /> White");
out.println("<input type=\"radio\" name=\"color\" value=\"black\" /> Black");
out.println("</form>");
}
public void drawCancelForm(String user,javax.servlet.jsp.JspWriter out) throws IOException
{
out.println("<form action=\"quitGame.jsp\" method=\"get\">");
out.println("<input type=\"hidden\" name=\"gameId\" value=\""+user+"\" />");
out.println("<input type=\"submit\" value=\"Cancel Game\" />");
out.println("</form>");
}
%>
<%
response.setHeader("Cache-Control","no-cache"); //Forces caches to obtain a new copy of the page from the origin server
response.setHeader("Cache-Control","no-store"); //Directs caches not to store the page under any circumstance
response.setDateHeader("Expires", 0); //Causes the proxy cache to see the page as "stale"
response.setHeader("Pragma","no-cache"); //HTTP 1.0 backward compatibility
%>
<html>
<head>
<link rel="stylesheet" href="styles.css" type="text/css" />
<title>Chess Online</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<%
if (Strings.dbCheckSession(request))
{
if(request.getParameter("error")!=null && request.getParameter("error").equals("opponentQuit"))
{
out.println("<br /><br />"+request.getParameter("error"));
}
out.println("<table border=\"0\" align=center>");
out.println("<tr><td rowspan=\"2\">");
drawJoinGameForm(out,application);
out.println("<br />
As soon as you join, your opponent, who is hosting the game, is on the move and your browser is waiting/loading.
");out.println("</td><td>");
drawHostGameForm(out);
out.println("</td><td>");
drawCancelForm((String)session.getAttribute("sessionUser"),out);
out.println("</td></tr>");
out.println("<tr><td align=\"right\" colspan=\"2\">");
out.println("
After hosting a game by clicking on the button 'Host New Game' your browser will be in process of loading a page."
+" As soon as an opponent joins your game you will be able to make the first move. If you do not wish to wait any longer for "
+"an opponent to join - click on 'Cancel Game'.
");out.println("</td></tr>");
out.println("</table>");
}
else response.sendRedirect(response.encodeURL("/jsp/index.jsp"));
%>
</body>
</html>
--end of chessOnline.jsp--
I also have a Read.class - its name doesn't mean anything - I have stored some out.println(); operations there - drawDesk(...), drawQuitForm(...), drawInfoForm(...) etc.
MY PROBLEM IS: THE SECOND TIME THE HOST PLAYS A MOVE HIS OPPONENT GETS A NULL INSTEAD OF VALID Game OBJECT. CAN ANYONE TELL ME WHY BECAUSE I HAVEN'T SET IT TO NULL ANYWHERE IN THE CODE

