Before I can do that, I have to finish the prototype and to do that, I
have to get a dynamically updating table working. It doesn't matter
whether individual cells or the whole table gets updated - it isn't
going to be large enough to make a visible difference to the user.
The table contains a fixed number of rows - one row for each service
that is being monitored. Each row contains the host name, name of
service, current status and {(if status is up a button to stop it) or
(if status is down a button to start it)}
The html currently looks like this:
<div>
<table>
<lift:comet type="Servers">
<tr>
<td>
<f:host_name>not available</f:host_name>
</td>
<td>
<f:service_name>not available</f:service_name>
</td>
<td>
<f:service_status>not available</f:service_status>
</td>
<td>button goes here</td>
</tr>
</lift:comet>
</table>
</div>
The current version of Servers.scala is shown below. Obviously, it
doesn't work, error:
XML Parsing Error: prefix not bound to a namespace
Location: http://protom2.stsci.edu:20035/liftdemo/
Line Number 106, Column 21: <f:host_name>not
available</f:host_name>
Binding looks like it should be fairly simple, except that binding
with Comet and binding with tables appear to be slightly different and
combining them is just confusing the heck out of me.
So if you have some comments or advice, I would be exceptionally grateful.
Donald
------------------ Servers.scala ------------------------------
package code.snippet
import xml.NodeSeq
import edu.stsci.meb.ModuleLoader
import edu.stsci.dads.service.{ServiceEntry, ServiceKey, EBServiceManager}
import collection.mutable.{ArrayBuffer, HashSet}
import net.liftweb.http.{RenderOut, CometActor}
import net.liftweb.common.Full
class Servers extends CometActor {
println("[Servers.init] enter.")
override def defaultPrefix = Full("f")
val serviceManager: EBServiceManager =
ModuleLoader.getRoleObject("services").asInstanceOf[EBServiceManager]
def render: RenderOut = {
val keys = serviceManager.getServices
val entries: ArrayBuffer[ServiceEntry] = new ArrayBuffer[ServiceEntry]
for (key <- keys) {
if (key.getServiceName.equals("YPServer")) {}
else {
val next = serviceManager.getEntry(key)
entries += next
}
}
val a: NodeSeq = entries.flatMap(entry => bind(
"host_name" --> entry.getKey.getHostName,
"service_name" --> entry.getKey.getServiceName,
"service_status" --> entry.getStatus.toString))
return new RenderOut(a)
}
}
--
Family photographs are a critical legacy for
ourselves and our descendants. Protect that
legacy with a digital backup and recovery plan.
Join the photo preservation advocacy Facebook group:
http://www.facebook.com/home.php?ref=logo#/group.php?gid=148274709288
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
This example looks good (though I don't quite follow all of the
syntax) except that it doesn't compile:
/Users/dmclean/IdeaProjects/dsb/dads/onegui_webapp/liftDemo/src/scala/code/comet/Servers.scala:20:
error: type mismatch;
found : Array[scala.xml.Node]
required: net.liftweb.http.RenderOut
key <- serviceManager.getServices if key.getServiceName == "YPServer"
^
one error found
Lift 2.0 w/Scala 2.7.7
Thank you,
Donald
The package naming was my error. I forgot to change it when I changed
it from a snippet.
This example looks good (though I don't quite follow all of the
syntax) except that it doesn't compile:
/Users/dmclean/IdeaProjects/dsb/dads/onegui_webapp/liftDemo/src/scala/code/comet/Servers.scala:20:
error: type mismatch;
found : Array[scala.xml.Node]
required: net.liftweb.http.RenderOut
key <- serviceManager.getServices if key.getServiceName == "YPServer"^
one error found
Lift 2.0 w/Scala 2.7.7
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
That is not just helpful, it is perfect.
I'm going to try and figure out the buttons and the updates (learn by
doing, ya know) but don't be surprised if I have questions...
Thank you again,
Donald
Thank you again,
Donald
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Ok then, I have three questions (see code for current version of
Servers.scala, below).
1. There seems to be a long delay between my pressing the button and
the call to ajaxStartStopHandler (several seconds). This doesn't seem
normal so what did I do wrong?
2. When ajaxStartStopHandler finally gets called, it gets called
twice. Again, what did I do wrong?
3. The definition of userContext is:
object userContext extends SessionVar[UserContext](null)
It is properly set (at least according to another part of the code)
but in CommandRunner it is always null. How can that be?
Thank you,
Donald
----------------------- Servers.scala
package code.comet
import xml.NodeSeq
import edu.stsci.meb.ModuleLoader
import collection.mutable.{ArrayBuffer, HashSet}
import net.liftweb.common.Full
import net.liftweb.http.{SHtml, RenderOut, CometActor}
import net.liftweb.http.js.JsCmd
import net.liftweb.http.js.JE.{JsRaw, Str}
import net.liftweb.util.Helpers.TimeSpan
import edu.stsci.dads.service.{ServiceStatus, ServiceEntry,
ServiceKey, EBServiceManager}
import net.liftweb.util.ActorPing
import net.liftweb.http.js.JsCmds.{Replace, Alert}
import edu.stsci.dads.agents.{CommandAgent, StopServerAgent, StartServerAgent}
import java.util.{HashMap, Date}
import code.snippet.userContext
class Servers extends CometActor {
println("[Servers.init] enter.")
override def defaultPrefix = Full("f")
val serviceManager: EBServiceManager =
ModuleLoader.getRoleObject("services").asInstanceOf[EBServiceManager]
val tickLength = new TimeSpan(2500L)
def ajaxStartStopHandler(str: String): JsCmd = {
println("[Servers.ajaxStartStopHandler] Received " + str)
val data = str.split(",")
new CommandRunner(data).start
Alert("Sending " + data(0))
}
def renderOutput(): NodeSeq =
<lift:embed what={"/template-servers"}/>
def render =
(for{
// get the keys, but only if they service name is NOT "YPServer"
key <- serviceManager.getServices if key.getServiceName != "YPServer"
// get the entry for the key
entry = serviceManager.getEntry(key)
// bind the entry to the template
node <- bind("host_name" -> entry.getKey.getHostName,
"service_name" -> entry.getKey.getServiceName,
"service_status" -> entry.getStatus.toString,
"button" -> button(entry))
// yield the results
} yield node): NodeSeq
def button(entry: ServiceEntry) = {
entry.getStatus match {
case ServiceStatus.up => <button
onclick={SHtml.ajaxCall(Str("stop," + entry.getKey.getHostName + "," +
entry.getKey.getServiceName), ajaxStartStopHandler
_)._2}>stop</button>
case ServiceStatus.down => <button
onclick={SHtml.ajaxCall(Str("start," + entry.getKey.getHostName + ","
+ entry.getKey.getServiceName), ajaxStartStopHandler
_)._2}>start</button>
case _ => <button enabled="false">waiting...</button>
}
}
// schedule a ping every 2.5 seconds so we redraw
ActorPing.schedule(this, Tick, tickLength)
override def lowPriority: PartialFunction[Any, Unit] = {
case Tick => {
println("[Servers.lowPriority] Got tick " + new Date());
Replace("serverContent", renderOutput)
// schedule an update in 2.5 seconds
ActorPing.schedule(this, Tick, tickLength)
}
}
}
class CommandRunner(data: Array[String]) extends Thread {
val commandMap = Map[String, CommandAgent]("start" -> new
StartServerAgent, "stop" -> new StopServerAgent)
override def run = {
println("[CommandRunner.run] enter.")
val agent = commandMap.get(data(0)).get
val executeData: HashMap[String, Object] = new HashMap[String, Object]
val context = userContext.get
println("[CommandRunner.run] context is: " + context)
executeData.put("context", context)
executeData.put("host", data(1))
executeData.put("server", data(2))
val result = agent.execute(executeData)
println("[CommandRunner.run] exit, result: " + result)
}
}
--
On Wed, Jul 7, 2010 at 2:07 PM, David Pollak
> Looking forward to your questions!Ok then, I have three questions (see code for current version of
Servers.scala, below).
1. There seems to be a long delay between my pressing the button and
the call to ajaxStartStopHandler (several seconds). This doesn't seem
normal so what did I do wrong?
2. When ajaxStartStopHandler finally gets called, it gets called
twice. Again, what did I do wrong?
3. The definition of userContext is:
object userContext extends SessionVar[UserContext](null)
It is properly set (at least according to another part of the code)
but in CommandRunner it is always null. How can that be?
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
I have two different Comet regions on the page that are supposed to be
updated by two different Comet actors. Doesn't seem to work though. Is
that because it can't be done that way or because I'm just doing
something stupid?
Thank you,
Donald
Thank you,
Donald
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Next: Is there a JsCmd that I can use that does nothing? I tried both:
Replace("serverContent", renderOutput)
Alert("Sending " + agent)
They appear to be the source of much slowness (the replace call took >
26 seconds)
Donald
Part of my problem was something stupid on my part.
Next: Is there a JsCmd that I can use that does nothing? I tried both:
Replace("serverContent", renderOutput)
Alert("Sending " + agent)
They appear to be the source of much slowness (the replace call took >
26 seconds)
Donald
--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Is there some reason why it's not listed in the scaladoc?
It should be listed in the ScalaDoc, otherwise it's useless. I was
looking in the scaladoc for JsCmd looking at the different choices and
IT ISN'T THERE which means that unless someone happens to already know
about it or is reading the source code, They Are Never Going To Find
It!
This is exactly the kind of thing that drives newbies crazy.
Donald
Unfortunately, that isn't very useful. In fact, I would categorize it
as useless for newbies since they probably would not think to look
there.
There isn't anywhere in the scaladoc where one can go to see what ALL
of the available (JsCmd)s are, regardless of how they are implemented.
That is what is really needed.
The point of ScalaDoc should be to explain the important information
about a class and that most definitely includes many things that the
Scala community does not presently include, as a rule. Terse code is
often good, terse documentation is often useless.
Donald