Hi all, I sent out the email below a little while ago, and I eventually got the solution to clone the fact when I create the object to be serialized. So, in the code below, in ExData.java, I changed the fact assignment to be assigned a clone of the fact that is a parameter of the constructor. I tried this and it worked just fine. However, I now have a problem where, in my real code, the number of facts is much greater than normal. From not using serialization to using serialization, I've not made any changes except those pertaining to serialization, so the problem must have to do with serialization and JESS. In any case, here is the problem: In my original code (which didn't use serialization, the server and client were one), I would periodically print out the number of times I had asserted a string into the JESS engine and I would also print out the number of total facts in the engine (the only way I could figure to do it was to get the Iterator for the list of facts and then count up the number of items in the iteration in a loop). In this original code, the number of facts in the engine was roughly 4 times the number of times I asserted a string. This was because each time I asserted a fact, within that fact were other "sub-facts" that were also asserted. The analogous variable in my example below is list-of-IDs. So I had a list of "sub-facts" that were asserted which were then used to link the "top-level" facts together.
Now, when I added in the serialization and the cloning, the number of facts in the engine jumped to 8 to 10 times the number of assertions. Can you think of any reason why this would happen? Does the cloning of a fact or serialization of a fact somehow affect the Rete itself? The bottom line is, I have a HUGE amount of data being processed and I am having an OutOfMemoryError because I have too many facts in the engine. I periodically retract top-level facts and sub-facts, but the ratio of 8 to 10 still remains. Any help would be highly appreciated. Thanks! - Nik. -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] Behalf Of Nik Joshi Sent: Friday, January 09, 2004 7:59 PM To: [EMAIL PROTECTED] Subject: JESS: java/jess serialization question Hi all, I posted this question a while ago without any code, and I got some replies which I tried, but to no avail. So I've coded a simplified version of my problem to demonstrate. I don't know if I can send attachments to this list, so I guess I'll have to put the code inline. Basically, I have a java server and client where the server has a Rete object running a JESS batch file. The JESS code periodically calls Userfunctions which, in turn, serialize the Fact data and send it to the client. The problem is that the data in the facts does not get sent over properly. When I de-serialize the data on the client end, some of the slot data in the facts is missing. In order to run my code (see below), you need four files: ExServer.java, ExClient.java, ExData.java, and Exbatch.txt. The server is run with this usage: java ExServer <port-number> <batch-file> and the client is run with this usage: java ExClient <server-host> <server-port>. After the client connects to the server, the server will prompt the user to press return. Every time the user presses return, a new fact will be asserted into the Rete. The facts are hardcoded into the server. Here is the output on the server side: >java ExServer 9988 Exbatch.txt Server is up... press return for first command... Executing command: (assert (alert (name "fact0") (ID 0) (list-of-IDs) (list-of-links cat rat dog))) Globbed new: fact0:0 and fact0:0 a2 is: (MAIN::alert (name "fact0") (ID 0) (list-of-IDs 0) (list-of-links cat rat dog)) about to send new cluster data... press return for next command... Executing command: (assert (alert (name "fact1") (ID 1) (list-of-IDs) (list-of-links penguin horse))) Globbed new: fact1:1 and fact1:1 a2 is: (MAIN::alert (name "fact1") (ID 1) (list-of-IDs 1) (list-of-links penguin horse)) about to send new cluster data... press return for next command... Executing command: (assert (alert (name "fact2") (ID 2) (list-of-IDs) (list-of-links sloth fish))) Globbed new: fact2:2 and fact2:2 a2 is: (MAIN::alert (name "fact2") (ID 2) (list-of-IDs 2) (list-of-links sloth fish)) about to send new cluster data... press return for next command... Executing command: (assert (alert (name "fact3") (ID 3) (list-of-IDs) (list-of-links rat horse sloth))) Globbed exists: fact2:2 and fact3:3 a2 is: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 2) (list-of-links rat horse sloth)) Globbed exists: fact3:3 and fact3:3 a2 is: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 3 2) (list-of-links rat horse sloth)) Globbed exists: fact3:3 and fact2:2 a2 is: (MAIN::alert (name "fact2") (ID 2) (list-of-IDs 3 2) (list-of-links sloth fish)) Globbed exists: fact1:1 and fact3:3 a2 is: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 1 3 2) (list-of-links rat horse sloth)) Globbed exists: fact3:3 and fact1:1 a2 is: (MAIN::alert (name "fact1") (ID 1) (list-of-IDs 3 1) (list-of-links penguin horse)) Globbed exists: fact0:0 and fact3:3 a2 is: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 0 1 3 2) (list-of-links rat horse sloth)) Globbed exists: fact3:3 and fact0:0 a2 is: (MAIN::alert (name "fact0") (ID 0) (list-of-IDs 3 0) (list-of-links cat rat dog)) Here is the output on the client side: >java ExClient localhost 9988 Establishing connection. Please wait ... Connected: Socket[addr=localhost/127.0.0.1,port=9988,localport=2126] waiting for objects... got object... Type: NEW f1: (MAIN::alert (name "fact0") (ID 0) (list-of-IDs 0) (list-of-links cat rat dog)) f2: (MAIN::alert (name "fact0") (ID 0) (list-of-IDs 0) (list-of-links cat rat dog)) got object... Type: NEW f1: (MAIN::alert (name "fact1") (ID 1) (list-of-IDs 1) (list-of-links penguin horse)) f2: (MAIN::alert (name "fact1") (ID 1) (list-of-IDs 1) (list-of-links penguin horse)) got object... Type: NEW f1: (MAIN::alert (name "fact2") (ID 2) (list-of-IDs 2) (list-of-links sloth fish)) f2: (MAIN::alert (name "fact2") (ID 2) (list-of-IDs 2) (list-of-links sloth fish)) got object... Type: MODIFY f1: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 2) (list-of-links rat horse sloth)) got object... Type: MODIFY f1: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 2) (list-of-links rat horse sloth)) got object... Type: MODIFY f1: (MAIN::alert (name "fact2") (ID 2) (list-of-IDs 2) (list-of-links sloth fish)) got object... Type: MODIFY f1: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 2) (list-of-links rat horse sloth)) got object... Type: MODIFY f1: (MAIN::alert (name "fact1") (ID 1) (list-of-IDs 1) (list-of-links penguin horse)) got object... Type: MODIFY f1: (MAIN::alert (name "fact3") (ID 3) (list-of-IDs 2) (list-of-links rat horse sloth)) got object... Type: MODIFY f1: (MAIN::alert (name "fact0") (ID 0) (list-of-IDs 0) (list-of-links cat rat dog)) Notice that when the server prints out a "Globbed exists" message, it immediately sends a "MODIFY" message to the client. So, for example, the second to the last "Globbed exists" corresponds to the second to last "MODIFY" message (a2 corresponds with f1). The problem is that the list-of-IDs multislot has gone from being "0 1 3 2" to simply "2". This happens with all of the "MODIFY"'s. Where is the extra data? In the code, I've used the "getIcon" routine to get the "real" fact, however, it doesn't matter whether I use it or not, I still get the same result. Any ideas? As always, any help is highly appreciated. Thanks! - Nik. ************************************************************ ExServer.java ------------- import java.net.*; import java.io.*; import java.util.*; import java.util.regex.*; import jess.*; import java.text.*; public class ExServer { private Socket socket = null; private Rete r = null; private String batchfile = null; private ObjectOutputStream clientout; public class ModifyCluster implements Userfunction { // params are: fact1 public String getName() { return ("modify-cluster"); } public Value call (ValueVector vv, Context context) throws JessException { Fact f1 = vv.get(1).factValue(context); ExData exd = new ExData (ExData.MODIFY, f1, null); try { clientout.writeObject (exd); } catch (IOException ioe) {System.out.println ("got ioe: " + ioe);} return (new Value (true)); } } public class NewCluster implements Userfunction { // params are: fact1, fact2 public String getName() { return ("new-cluster"); } public Value call (ValueVector vv, Context context) throws JessException { Fact f1 = vv.get(1).factValue(context); Fact f2 = vv.get(2).factValue(context); ExData exd = new ExData (ExData.NEW, f1, f2); System.out.println ("about to send new cluster data..."); try { clientout.writeObject (exd); } catch (IOException ioe) {System.out.println ("got ioe: " + ioe);} return (new Value (true)); } } public ExServer (int serverPort, String batchname) throws IOException { Socket clientsocket; batchfile = batchname; start(); ServerSocket ss = new ServerSocket (serverPort); System.out.println ("Server is up..."); clientsocket = ss.accept(); clientout = new ObjectOutputStream (new BufferedOutputStream (clientsocket.getOutputStream())); String line = ""; String factstring = null; BufferedReader in = new BufferedReader (new InputStreamReader (System.in)); int index = 0; String factstrings[] = new String[4]; factstrings[0] = "(assert (alert (name \"fact0\") (ID 0) (list-of-IDs) (list-of-links cat rat dog)))"; factstrings[1] = "(assert (alert (name \"fact1\") (ID 1) (list-of-IDs) (list-of-links penguin horse)))"; factstrings[2] = "(assert (alert (name \"fact2\") (ID 2) (list-of-IDs) (list-of-links sloth fish)))"; factstrings[3] = "(assert (alert (name \"fact3\") (ID 3) (list-of-IDs) (list-of-links rat horse sloth)))"; System.out.println ("press return for first command..."); try { while (in.readLine() != null) { System.out.println ("Executing command: " + factstrings[index]); r.executeCommand (factstrings[index]); r.run(); index++; clientout.flush(); System.out.println ("press return for next command..."); } } catch (JessException je) {System.out.println ("got jess exception: "+je.getMessage()+" on line "+je.getLineNumber()); System.out.println ("program text: "+je.getProgramText()); System.out.println ("extra data: "+je.getData()); System.out.println ("in routine: "+je.getRoutine()); System.out.println ("context: "+je.getContext()); System.out.println ("cause: "+je.getCause().toString()+"\n");} catch (SocketException se) {System.out.println (se.toString()); System.exit(1);} } /* end ExServer constructor */ public void start() throws IOException { r = new Rete(); r.addUserfunction (new NewCluster()); r.addUserfunction (new ModifyCluster()); try { r.executeCommand ("(batch " + batchfile + ")"); } catch (JessException je) { System.out.println ("jess error: "+je.getMessage()+" on line "+je.getLineNumber()+"\n"); System.out.println ("Program text: "+je.getProgramText()+"\n"); System.exit(1); } } public void stop() { try { if (socket != null) {socket.close();} } catch(IOException ioe) {System.out.println("Error closing ...");} } public static void main (String args[]) throws IOException { ExServer client = null; if (args.length != 2) System.out.println ("Usage: java ExServer port batchfile"); else client = new ExServer (Integer.parseInt(args[0]), args[1]); } } *********************************************************************** ExClient.java ------------- import java.net.*; import java.io.*; import java.util.*; import java.util.regex.*; import jess.*; public class ExClient { public ExClient (String serverName, int serverPort) throws IOException { Socket socket = null; ObjectInputStream in = null; System.out.println ("Establishing connection. Please wait ..."); try { socket = new Socket (serverName, serverPort); System.out.println ("Connected: " + socket); } catch(UnknownHostException uhe) {System.out.println("Host unknown: " + uhe.getMessage()); System.exit(1);} catch(IOException ioe) {System.out.println("Unexpected exception: " + ioe.getMessage()); System.exit(1);} in = new ObjectInputStream (new BufferedInputStream (socket.getInputStream())); System.out.println ("waiting for objects..."); ExData theobj; try { while ((theobj = (ExData) in.readObject()) != null) { System.out.println ("got object..."); theobj.print(); System.out.println(); } } catch (SocketException se) {System.out.println (se.toString()); System.exit(1);} catch (ClassNotFoundException cnfe) {System.err.println ("class not found");} } /* end ExClient constructor */ public static void main (String args[]) throws IOException { ExClient client = null; if (args.length != 2) System.out.println ("Usage: java ExClient host port"); else client = new ExClient (args[0], Integer.parseInt(args[1])); } } *********************************************************** ExData.java ----------- import java.io.*; import jess.*; import java.util.Vector; public class ExData extends Object implements Serializable { public static final int NEW = 0; public static final int MODIFY = 1; public static final int DELETE = 2; public static final int END = 3; public int type; public Fact f1; public Fact f2; public ExData (int type, Fact f1, Fact f2) { this.type = type; this.f1 = f1; this.f2 = f2; } public void print() { if (type==NEW) {System.out.println ("Type: NEW");} else if (type==MODIFY) {System.out.println ("Type: MODIFY");} else if (type==DELETE) {System.out.println ("Type: DELETE");} else if (type==END) {System.out.println ("Type: END");} if (f1 != null) {System.out.println ("f1: " + f1.toString());} if (f2 != null) {System.out.println ("f2: " + f2.toString() + "\n");} } } ******************************************************** Exbatch.txt ----------- (clear) (reset) (deftemplate alert (slot name (type STRING)) (slot ID) (multislot list-of-IDs) (multislot list-of-links) ) ; if cluster exists (defrule alertglob2 (declare (salience 200)) ?a2 <- (alert (name ?name2) (ID ?id2) (list-of-links $? ?link2 $?) (list-of-IDs $?list2)) ?a1 <- (alert (name ?name1) (ID ?id1) (list-of-links $? ?link2 $?) (list-of-IDs $?list1)) (test (> (length$ $?list1) 0)) (test (not (member$ ?id1 $?list2))) => (printout t "Globbed exists: " ?name1 ":" ?id1 " and " ?name2 ":" ?id2 crlf) (modify ?a2 (list-of-IDs (insert$ $?list2 1 ?id1))) (printout t "a2 is: " (?a2 toString) crlf crlf) (modify-cluster (?a2 getIcon)) ) ; if cluster does not exist (defrule alertglob1 (declare (salience 100)) ?a2 <- (alert (name ?name2) (ID ?id2) (list-of-links $? ?link2 $?) (list-of-IDs $?list2)) ?a1 <- (alert (name ?name1) (ID ?id1) (list-of-links $? ?link2 $?) (list-of-IDs $?list1)) (test (not (member$ ?id1 $?list2))) => (printout t "Globbed new: " ?name1 ":" ?id1 " and " ?name2 ":" ?id2 crlf) (modify ?a2 (list-of-IDs (insert$ $?list2 1 ?id1))) (printout t "a2 is: " (?a2 toString) crlf crlf) (new-cluster (?a1 getIcon) (?a2 getIcon)) ;(printout t "finished alertglob1" crlf) ; (facts) ) -------------------------------------------------------------------- To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]' in the BODY of a message to [EMAIL PROTECTED], NOT to the list (use your own address!) List problems? Notify [EMAIL PROTECTED] -------------------------------------------------------------------- -------------------------------------------------------------------- To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]' in the BODY of a message to [EMAIL PROTECTED], NOT to the list (use your own address!) List problems? Notify [EMAIL PROTECTED] --------------------------------------------------------------------
