Created
April 26, 2011 15:53
-
-
Save contextfw/942528 to your computer and use it in GitHub Desktop.
Example: Chat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class Chat extends Component implements ChatServiceClient { | |
| @Inject | |
| private ChatService service; | |
| private long lastAccess = -1; | |
| @Element | |
| public List<ChatMsg> messages() { | |
| return service.getMessages(); | |
| } | |
| @AfterBuild | |
| public void afterBuild() { | |
| lastAccess = service.getLastAccess(); | |
| } | |
| @Attribute | |
| public boolean changed() { | |
| return service.getLastAccess() > lastAccess; | |
| } | |
| @Remoted | |
| @Delayed(ChatService.class) | |
| public void checkMessages() { | |
| System.out.println("Checking messages"); | |
| refresh(); | |
| } | |
| @ScriptElement(onCreate=false) | |
| public Script jsUpdate() { | |
| return new JsUpdate(this, "checkMessages"); | |
| } | |
| @ScriptElement(onUpdate=false) | |
| public Script jsInit() { | |
| return new JsInit(this); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Chat = Component.extend({ | |
| init : function(id) { | |
| this._super(id); | |
| var self = this; | |
| setTimeout(function() { self.checkMessages() }, 1000); | |
| }, | |
| checkMessages : function() { | |
| this.call("checkMessages")(); | |
| } | |
| }); | |
| ChatInput = Component.extend({ | |
| init : function(id) { | |
| var self = this; | |
| this._super(id); | |
| this.attach(); | |
| }, | |
| attach : function() { | |
| var self = this; | |
| this.el("newmsg").keypress(function(e) { | |
| if(e.which==13) { | |
| e.preventDefault(); | |
| self.addMessage(); | |
| } | |
| }); | |
| this.el("button").click(function() { | |
| self.addMessage() | |
| }); | |
| }, | |
| addMessage : function() { | |
| var self = this; | |
| var msg = this.el("newmsg"); | |
| this.call("addMessage", null, function() { | |
| self.el("newmsg").focus(); | |
| })(msg.val()); | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | |
| <xsl:template match="Chat"> | |
| <div id="{@id}"> | |
| <xsl:call-template name="Chat" /> | |
| </div> | |
| </xsl:template> | |
| <xsl:template match="Chat.update"> | |
| <xsl:if test="@changed='true'"> | |
| <replaceInner id="{@id}"> | |
| <xsl:call-template name="Chat" /> | |
| </replaceInner> | |
| </xsl:if> | |
| </xsl:template> | |
| <xsl:template name="Chat"> | |
| <ul> | |
| <xsl:for-each select="messages/ChatMsg"> | |
| <li> | |
| <b><xsl:value-of select="@sent" /></b>: | |
| <xsl:value-of select="msg" /> | |
| <i> (expires: <xsl:value-of select="@expires" />)</i> | |
| </li> | |
| </xsl:for-each> | |
| </ul> | |
| </xsl:template> | |
| </xsl:stylesheet> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class ChatInput extends Component { | |
| @Inject | |
| private ChatService service; | |
| @Remoted | |
| public void addMessage(String msg) { | |
| service.addMessage(msg); | |
| refresh(); | |
| } | |
| @ScriptElement | |
| public Script init() { | |
| return new ComponentFunctionCall(this, "init"); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?xml version="1.0" encoding="UTF-8"?> | |
| <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> | |
| <xsl:template match="ChatInput"> | |
| <div id="{@id}"> | |
| <xsl:call-template name="ChatInput" /> | |
| </div> | |
| </xsl:template> | |
| <xsl:template match="ChatInput.update"> | |
| <replaceInner id="{@id}"> | |
| <xsl:call-template name="ChatInput" /> | |
| </replaceInner> | |
| </xsl:template> | |
| <xsl:template name="ChatInput"> | |
| <input type="text" id="{@id}_newmsg" /> | |
| <input id="{@id}_button" type="button" | |
| class="button" | |
| value="Add (or press enter)" /> | |
| </xsl:template> | |
| </xsl:stylesheet> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Singleton | |
| public class ChatService implements DelayedUpdateHandler<ChatServiceClient>, Runnable { | |
| private final LinkedList<ChatMsg> messages = new LinkedList<ChatMsg>(); | |
| private final static long expiration = 1000 * 25; | |
| private long lastAccess = System.currentTimeMillis(); | |
| private final Set<Continuation> continuations = new HashSet<Continuation>(); | |
| private ScheduledThreadPoolExecutor invoker = new ScheduledThreadPoolExecutor(1); | |
| public List<ChatMsg> getMessages() { | |
| return Collections.unmodifiableList(messages); | |
| } | |
| private void schedule(ChatMsg msg) { | |
| invoker.schedule(this, msg.getExpires().getMillis() - System.currentTimeMillis(), | |
| TimeUnit.MILLISECONDS); | |
| } | |
| public void addMessage(String value) { | |
| ChatMsg msg = new ChatMsg( | |
| new DateTime(System.currentTimeMillis()), | |
| new DateTime(System.currentTimeMillis() + expiration), | |
| value); | |
| synchronized (continuations) { | |
| if (messages.size() > 9) { | |
| invoker.remove(this); | |
| messages.removeFirst(); | |
| } | |
| messages.add(msg); | |
| schedule(messages.getFirst()); | |
| notifyChats(); | |
| } | |
| } | |
| private void notifyChats() { | |
| lastAccess = System.currentTimeMillis(); | |
| synchronized (continuations) { | |
| Iterator<Continuation> iter = continuations.iterator(); | |
| while (iter.hasNext()) { | |
| // System.out.println("Has next"); | |
| try { | |
| iter.next().resume(); | |
| } catch (Exception e) { | |
| // Just swallow it | |
| } finally { | |
| iter.remove(); | |
| } | |
| } | |
| } | |
| } | |
| @Override | |
| public boolean isUpdateDelayed(ChatServiceClient chat, HttpServletRequest request) { | |
| Continuation continuation = ContinuationSupport | |
| .getContinuation(request); | |
| synchronized (continuations) { | |
| if (continuations.contains(continuation)) { | |
| continuations.remove(continuation); | |
| return false; | |
| } else { | |
| if (chat.changed()) { | |
| return false; | |
| } else { | |
| continuations.add(continuation); | |
| continuation.suspend(); | |
| return true; | |
| } | |
| } | |
| } | |
| } | |
| public long getLastAccess() { | |
| return lastAccess; | |
| } | |
| @Override | |
| public void run() { | |
| synchronized (continuations) { | |
| if (messages.size() > 0) { | |
| while (messages.size() > 0 | |
| && messages.getFirst().getExpires().getMillis() <= System | |
| .currentTimeMillis()) { | |
| messages.removeFirst(); | |
| } | |
| notifyChats(); | |
| } | |
| if (messages.size() > 0) { | |
| schedule(messages.getFirst()); | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public interface ChatServiceClient { | |
| boolean changed(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment