Skip to content
This repository was archived by the owner on Jul 8, 2025. It is now read-only.

Commit c17af7c

Browse files
committed
use DELETE and POST to kill and create agents
1 parent 7dda588 commit c17af7c

File tree

3 files changed

+117
-57
lines changed

3 files changed

+117
-57
lines changed

readme.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,24 @@ See ClientTest.java for an example of Java client. It can be run with `gradle te
2626

2727
## for machine (or intelligent humans)
2828

29+
* POST `/agents/{agentname}`
30+
creates a new agent.
31+
32+
* DELETE `/agents/{agentname}`
33+
Kills the agent.
34+
2935
* POST XML `/agents/{agentname}/mb`
3036
Adds a message in the agent's mailbox. See class Message.java for details of the fields.
3137

3238
* GET XML `/agents/{agentname}/all`
3339
returns the mind state of the agent
3440

3541
* GET TXT /agents/{agentname}/plans
36-
return the agent's plans
42+
returns the agent's plans. A label can be used as argument:
43+
/agents/{agentname}/plans?label=planT
44+
45+
* POST FORM /agents/{agentname}/plans
46+
upload some plans in the agent's plan library
47+
3748

3849
See RestImpl.java for more

src/java/jacamo/web/JCMRest.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
2727
import org.glassfish.jersey.server.ResourceConfig;
2828

29-
import jacamo.infra.JaCaMoLauncher;
3029
import jacamo.infra.JaCaMoRuntimeServices;
3130
import jacamo.platform.DefaultPlatformImpl;
3231
import jason.asSemantics.Agent;
32+
import jason.infra.centralised.BaseCentralisedMAS;
3333
import jason.mas2j.AgentParameters;
3434
import jason.mas2j.ClassParameters;
3535
import jason.runtime.Settings;
@@ -40,7 +40,6 @@ public class JCMRest extends DefaultPlatformImpl {
4040
public static String JaCaMoZKAgNodeId = "/jacamo/agents";
4141
public static String JaCaMoZKDFNodeId = "/jacamo/df";
4242

43-
JaCaMoLauncher runner = null;
4443
HttpServer restHttpServer = null;
4544

4645
static URI restServerURI = null;
@@ -116,7 +115,7 @@ public void init(String[] args) throws Exception {
116115
}
117116

118117
// replace createAgent service (to add RestAgArch)
119-
((JaCaMoLauncher)JaCaMoLauncher.getRunner()).setRuntimeServives(new JaCaMoRuntimeServices(JaCaMoLauncher.getRunner()) {
118+
BaseCentralisedMAS.getRunner().setRuntimeServives(new JaCaMoRuntimeServices(BaseCentralisedMAS.getRunner()) {
120119
@Override
121120
public String createAgent(String agName, String agSource, String agClass, List<String> archClasses, ClassParameters bbPars, Settings stts, Agent father) throws Exception {
122121
if (archClasses == null)
@@ -127,7 +126,7 @@ public String createAgent(String agName, String agSource, String agClass, List<S
127126
}
128127
});
129128

130-
this.runner = (JaCaMoLauncher)JaCaMoLauncher.getRunner();
129+
//this.runner = (JaCaMoLauncher)JaCaMoLauncher.getRunner();
131130
}
132131

133132
@Override

src/java/jacamo/web/RestImpl.java

Lines changed: 102 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
import java.io.InputStream;
44
import java.io.StringReader;
55
import java.io.StringWriter;
6-
import java.util.ArrayList;
76
import java.util.HashMap;
8-
import java.util.List;
97
import java.util.Map;
108
import java.util.Set;
119
import java.util.logging.LogRecord;
@@ -29,7 +27,6 @@
2927
import org.glassfish.jersey.media.multipart.FormDataParam;
3028
import org.w3c.dom.Document;
3129

32-
import jacamo.infra.JaCaMoLauncher;
3330
import jason.ReceiverNotFoundException;
3431
import jason.asSemantics.Agent;
3532
import jason.asSemantics.IntendedMeans;
@@ -42,6 +39,7 @@
4239
import jason.asSyntax.PlanBody;
4340
import jason.asSyntax.PlanLibrary;
4441
import jason.asSyntax.Trigger;
42+
import jason.infra.centralised.BaseCentralisedMAS;
4543
import jason.infra.centralised.CentralisedAgArch;
4644
import jason.util.Config;
4745
import jason.util.asl2html;
@@ -78,7 +76,7 @@ public String getAgentsHtml() {
7876
so.append("<html><head><title>Jason (list of agents)</title> <meta http-equiv=\"refresh\" content=\"3\"/> </head><body>");
7977
so.append("<font size=\"+2\"><p style='color: red; font-family: arial;'>Agents</p></font>");
8078
if (JCMRest.getZKHost() == null) {
81-
for (String a: JaCaMoLauncher.getRunner().getAgs().keySet()) {
79+
for (String a: BaseCentralisedMAS.getRunner().getAgs().keySet()) {
8280
so.append("- <a href=\"/agents/"+a+"/all\" target=\"am\" style=\"font-family: arial; text-decoration: none\">"+a+"</a><br/>");
8381
}
8482
} else {
@@ -87,20 +85,29 @@ public String getAgentsHtml() {
8785
for (String a: JCMRest.getZKClient().getChildren().forPath(JCMRest.JaCaMoZKAgNodeId)) {
8886
String url = new String(JCMRest.getZKClient().getData().forPath(JCMRest.JaCaMoZKAgNodeId+"/"+a));
8987
so.append("- <a href=\""+url+"/all\" target=\"am\" style=\"font-family: arial; text-decoration: none\">"+a+"</a><br/>");
88+
Agent ag = getAgent(a);
89+
if (ag != null) createAgLog(a, ag);
9090
}
9191
} catch (Exception e) {
9292
e.printStackTrace();
9393
}
9494
}
9595

96-
so.append("<br/><a href=\"/new_agent_form\" target=\"am\" style=\"font-family: arial; text-decoration: none\">new agent</a>");
96+
so.append("<br/><a href=\"/forms/new_agent\" target=\"am\" style=\"font-family: arial; text-decoration: none\">new agent</a>");
9797
so.append("<br/><a href=\"/services\" target=\"am\" style=\"font-family: arial; text-decoration: none\">DF</a><br/>");
9898

9999
so.append("<hr/>by <a href=\"http://jason.sf.net\" target=\"_blank\">Jason</a>");
100100
so.append("</body></html>");
101101
return so.toString();
102102
}
103103

104+
private Agent getAgent(String agName) {
105+
CentralisedAgArch cag = BaseCentralisedMAS.getRunner().getAg(agName);
106+
if (cag != null)
107+
return cag.getTS().getAg();
108+
else
109+
return null;
110+
}
104111

105112
/** AGENT **/
106113

@@ -148,27 +155,37 @@ public String setShow(@PathParam("agentname") String agName,
148155

149156
static String helpMsg1 = "Example: +bel; !goal; .send(bob,tell,hello); +{+!goal <- .print(ok) });";
150157

151-
@Path("/new_agent_form")
158+
@Path("/forms/new_agent")
152159
@GET
153160
@Produces(MediaType.TEXT_HTML)
154161
public String getNewAgentForm() {
155162
return "<html><head><title>new agent form</title></head>"+
156-
"<form action=\"/new_agent\" method=\"post\">" +
157-
"Name: <input type=\"text\" name=\"name\" />"+
158-
"<input type=\"submit\" value=\"create\">"+
163+
"<input type=\"text\" name=\"name\" size=\"43\" id=\"inputcmd\" placeholder='enter the name of the agent' onkeydown=\"if (event.keyCode == 13) runCMD()\" />\n" +
164+
"<script language=\"JavaScript\">\n" +
165+
" function runCMD() {\n" +
166+
" http = new XMLHttpRequest();\n" +
167+
" http.open(\"POST\", '/agents/'+document.getElementById('inputcmd').value, false); \n" +
168+
" http.send();\n"+
169+
" window.location.href = '/agents/'+document.getElementById('inputcmd').value+'/all';\n"+
170+
" }\n" +
171+
"</script>"+
159172
"</form></html>";
160173
}
161174

162-
@Path("/new_agent")
175+
@Path("/agents/{agentname}")
163176
@POST
164-
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
177+
//@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
178+
//@Consumes(MediaType.TEXT_PLAIN)
165179
@Produces(MediaType.TEXT_HTML)
166-
public String createNewAgent(@FormParam("name") String agName) {
180+
public String createNewAgent(@PathParam("agentname") String agName) { //@FormParam("name") String agName) {
167181
try {
168-
String name = JaCaMoLauncher.getRunner().getRuntimeServices().createAgent(agName, null, null, null, null, null, null);
169-
JaCaMoLauncher.getRunner().getRuntimeServices().startAgent(name);
182+
String name = BaseCentralisedMAS.getRunner().getRuntimeServices().createAgent(agName, null, null, null, null, null, null);
183+
BaseCentralisedMAS.getRunner().getRuntimeServices().startAgent(name);
170184
// set some source for the agent
171-
JaCaMoLauncher.getRunner().getAg(name).getTS().getAg().setASLSrc("no-inicial.asl");
185+
Agent ag = getAgent(name);
186+
ag.setASLSrc("no-inicial.asl");
187+
createAgLog(agName, ag);
188+
172189
return "<head><meta http-equiv=\"refresh\" content=\"2; URL='/agents/"+name+"/all'\" /></head>ok for "+name;
173190
} catch (Exception e) {
174191
e.printStackTrace();
@@ -205,6 +222,11 @@ public String getAgentHtml(@PathParam("agentname") String agName) {
205222
//" document.getElementById('debug').innerHTML = data\n" +
206223
" http.send(data);\n"+
207224
" }\n" +
225+
" function killAg() {\n" +
226+
" h2 = new XMLHttpRequest();\n" +
227+
" h2.open('DELETE', '/agents/"+agName+"', false); \n" +
228+
" h2.send(); \n" +
229+
" }\n" +
208230
" function delLog() {\n" +
209231
" h2 = new XMLHttpRequest();\n" +
210232
" h2.open('DELETE', 'log', false); \n" +
@@ -215,7 +237,7 @@ public String getAgentHtml(@PathParam("agentname") String agName) {
215237
" http.onreadystatechange = function() { \n" +
216238
" if (http.readyState == 4 && http.status == 200) {\n" +
217239
" document.getElementById('log').innerHTML = http.responseText;\n" +
218-
" if (http.responseText.length > 10) {\n" +
240+
" if (http.responseText.length > 1) {\n" +
219241
" var btn = document.createElement(\"BUTTON\"); \n" +
220242
" var t = document.createTextNode(\"clear log\");\n" +
221243
" btn.appendChild(t); \n" +
@@ -235,27 +257,31 @@ public String getAgentHtml(@PathParam("agentname") String agName) {
235257
}
236258
for (String p: show.keySet())
237259
mindInspectorTransformerHTML.setParameter("show-"+p, show.get(p)+"");
238-
so.append( mindInspectorTransformerHTML.transform( JaCaMoLauncher.getRunner().getAg(agName).getTS().getAg().getAgState() )); // transform to HTML
260+
Agent ag = getAgent(agName);
261+
if (ag != null) {
262+
so.append( mindInspectorTransformerHTML.transform( ag.getAgState() )); // transform to HTML
263+
} else {
264+
// TODO: use the rest API to get the agent HTML in the remote host
265+
}
239266

240267
so.append("<hr/><a href='plans' style='font-family: arial; text-decoration: none'>list plans</a>, &nbsp;");
241268
so.append("<a href='load_plans_form' style='font-family: arial; text-decoration: none'>upload plans</a>, &nbsp;");
242-
so.append("<a href='kill' style='font-family: arial; text-decoration: none'>kill this agent</a>");
269+
so.append("<a href='kill' onclick='killAg()' style='font-family: arial; text-decoration: none'>kill this agent</a>");
243270
} catch (Exception e) {
244-
if (JaCaMoLauncher.getRunner().getAg(agName) != null)
245-
e.printStackTrace();
271+
e.printStackTrace();
246272
so.append("Agent "+agName+" does not exist or cannot be observed.");
247273
}
248274

249275
so.append("</body></html>");
250276
return so.toString();
251277
}
252278

253-
@Path("/agents/{agentname}/kill")
254-
@GET
279+
@Path("/agents/{agentname}")
280+
@DELETE
255281
@Produces(MediaType.TEXT_PLAIN)
256282
public String killAgent(@PathParam("agentname") String agName) throws ReceiverNotFoundException {
257283
try {
258-
return "result of kill: "+JaCaMoLauncher.getRunner().getRuntimeServices().killAgent(agName,"web");
284+
return "result of kill: "+BaseCentralisedMAS.getRunner().getRuntimeServices().killAgent(agName,"web");
259285
} catch (Exception e) {
260286
return "Agent "+agName+" in unknown."+e.getMessage();
261287
}
@@ -266,14 +292,14 @@ public String killAgent(@PathParam("agentname") String agName) throws ReceiverNo
266292
@Produces(MediaType.TEXT_HTML)
267293
public String getLoadPlansForm(@PathParam("agentname") String agName) {
268294
return "<html><head><title>load plans for "+agName+"</title></head>"+
269-
"<form action=\"/agents/"+agName+"/load_plans\" method=\"post\" id=\"usrform\" enctype=\"multipart/form-data\">" +
295+
"<form action=\"/agents/"+agName+"/plans\" method=\"post\" id=\"usrform\" enctype=\"multipart/form-data\">" +
270296
"Enter Jason code below:<br/><textarea name=\"plans\" form=\"usrform\" placeholder=\"optinally, write plans here\" rows=\"13\" cols=\"62\" ></textarea>" +
271297
"<br/>or upload a file: <input type=\"file\" name=\"file\">"+
272298
"<br/><input type=\"submit\" value=\"Upload it\">"+
273299
"</form></html>";
274300
}
275301

276-
@Path("/agents/{agentname}/load_plans")
302+
@Path("/agents/{agentname}/plans")
277303
@POST
278304
@Consumes(MediaType.MULTIPART_FORM_DATA)
279305
@Produces(MediaType.TEXT_HTML)
@@ -283,10 +309,16 @@ public String loadPlans(@PathParam("agentname") String agName,
283309
@FormDataParam("file") FormDataContentDisposition fileDetail
284310
) {
285311
try {
286-
Agent ag = JaCaMoLauncher.getRunner().getAg(agName).getTS().getAg();
287-
ag.parseAS(new StringReader(plans), "RrestAPI");
288-
ag.load(uploadedInputStream, "restAPI://"+fileDetail.getFileName());
289-
return "<head><meta http-equiv=\"refresh\" content=\"2; URL='/agents/"+agName+"/all'\" /></head>ok, code uploaded!";
312+
String r = "nok";
313+
Agent ag = getAgent(agName);
314+
if (ag != null) {
315+
ag.parseAS(new StringReader(plans), "RrestAPI");
316+
ag.load(uploadedInputStream, "restAPI://"+fileDetail.getFileName());
317+
r = "ok, code uploaded!";
318+
} else {
319+
// TODO: use rest API to load in the remote agent
320+
}
321+
return "<head><meta http-equiv=\"refresh\" content=\"2; URL='/agents/"+agName+"/all'\" /></head>"+r;
290322
} catch (Exception e) {
291323
e.printStackTrace();
292324
return "error "+e.getMessage();
@@ -298,7 +330,12 @@ public String loadPlans(@PathParam("agentname") String agName,
298330
@Produces(MediaType.APPLICATION_XML)
299331
public Document getAgentXml(@PathParam("agentname") String agName) {
300332
try {
301-
return JaCaMoLauncher.getRunner().getAg(agName).getTS().getAg().getAgState();
333+
Agent ag = getAgent(agName);
334+
if (ag != null)
335+
return ag.getAgState();
336+
else
337+
// TODO: use rest API to load in the remote agent
338+
return null;
302339
} catch (Exception e) {
303340
e.printStackTrace();
304341
return null;
@@ -313,11 +350,16 @@ public String getAgentPlansTxt(@PathParam("agentname") String agName,
313350
@DefaultValue("all") @QueryParam("label") String label) {
314351
StringWriter so = new StringWriter();
315352
try {
316-
PlanLibrary pl = JaCaMoLauncher.getRunner().getAg(agName).getTS().getAg().getPL();
317-
if (label.equals("all"))
318-
so.append(pl.getAsTxt(false));
319-
else
320-
so.append(pl.get(label).toASString());
353+
Agent ag = getAgent(agName);
354+
if (ag != null) {
355+
PlanLibrary pl = ag.getPL();
356+
if (label.equals("all"))
357+
so.append(pl.getAsTxt(false));
358+
else
359+
so.append(pl.get(label).toASString());
360+
} else {
361+
// TODO: use rest API to load in the remote agent
362+
}
321363
} catch (Exception e) {
322364
e.printStackTrace();
323365
so.append("Agent "+agName+" does not exist or cannot be observed.");
@@ -343,7 +385,6 @@ public String runCmdPost(@FormParam("c") String cmd, @PathParam("agentname") Str
343385
public String getLogOutput(@PathParam("agentname") String agName) {
344386
StringBuilder o = agLog.get(agName);
345387
if (o != null) {
346-
//agLog.put(agName, new StringBuilder());
347388
return o.toString();
348389
}
349390
return "";
@@ -370,26 +411,35 @@ String execCmd(String agName, String sCmd) {
370411
new Unifier()),
371412
te));
372413

373-
TransitionSystem ts = JaCaMoLauncher.getRunner().getAg(agName).getTS();
374-
ts.getC().addRunningIntention(i);
375-
ts.getUserAgArch().wake();
376-
377-
// adds a log for the agent
378-
if (agLog.get(agName) == null) {
379-
ts.getLogger().addHandler( new StreamHandler() {
380-
@Override
381-
public void publish(LogRecord l) {
382-
addAgLog(agName, l.getMessage());
383-
}
384-
});
414+
Agent ag = getAgent(agName);
415+
if (ag != null) {
416+
TransitionSystem ts = ag.getTS();
417+
ts.getC().addRunningIntention(i);
418+
ts.getUserAgArch().wake();
419+
createAgLog(agName, ag);
420+
return "included for execution";
421+
} else {
422+
// TODO: use rest API to load in the remote agent
423+
return "not implemented";
385424
}
386-
387-
return "included for execution";
388425
} catch (Exception e) {
389426
return("Error parsing "+sCmd+"\n"+e);
390427
}
391428
}
392429

430+
protected void createAgLog(String agName, Agent ag) {
431+
// adds a log for the agent
432+
if (agLog.get(agName) == null) {
433+
agLog.put(agName, new StringBuilder());
434+
ag.getTS().getLogger().addHandler( new StreamHandler() {
435+
@Override
436+
public void publish(LogRecord l) {
437+
addAgLog(agName, l.getMessage());
438+
}
439+
});
440+
}
441+
}
442+
393443
protected void addAgLog(String agName, String msg) {
394444
StringBuilder o = agLog.get(agName);
395445
if (o == null) {
@@ -407,7 +457,7 @@ protected void addAgLog(String agName, String msg) {
407457
@Consumes(MediaType.APPLICATION_XML)
408458
@Produces(MediaType.TEXT_PLAIN)
409459
public String addAgMsg(Message m, @PathParam("agentname") String agName) {
410-
CentralisedAgArch a = JaCaMoLauncher.getRunner().getAg(agName);
460+
CentralisedAgArch a = BaseCentralisedMAS.getRunner().getAg(agName);
411461
if (a != null) {
412462
a.receiveMsg(m.getAsJasonMsg());
413463
return "ok";
@@ -431,7 +481,7 @@ public String getAgentHtml() {
431481
so.append("<tr style='background-color: #ece7e6; font-family: arial;'><td><b>Agent</b></td><td><b>Services</b></td></tr>");
432482
if (JCMRest.getZKHost() == null) {
433483
// get DF locally
434-
Map<String, Set<String>> df = JaCaMoLauncher.getRunner().getDF();
484+
Map<String, Set<String>> df = BaseCentralisedMAS.getRunner().getDF();
435485
for (String a: df.keySet()) {
436486
so.append("<tr style='font-family: arial;'><td>"+a+"</td>");
437487
for (String s: df.get(a)) {

0 commit comments

Comments
 (0)