I needed:
- Cross-browser support
- No need for broadcast messages
- Ability to send messages to specific clients
I tried to follow the primer on the cometd project site. It didn't work, bit gave me a good starting point. I ended up with a directory layout like:
jetty7-test
|-- pom.xml
\-- src
\-- main
|-- java
| \-- test
| \-- cometd
| \-- PrivateServlet.java
\-- webapp
|-- index.html
\-- WEB-INF
|-- web.xml
pom.xml
Thepom.xml looks like this:<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test.cometd</groupId>
<artifactId>jetty7-test</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<overlays>
<overlay />
</overlays>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>7.0.0.v20091005</version>
<configuration>
<!-- uncommet to scan for updates while running -->
<!-- <scanIntervalSeconds>10</scanIntervalSeconds> -->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- needed since for me it defaults to java 1.3 compiling -->
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- get Jetty and cometd-java -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.cometd.java</groupId>
<artifactId>cometd-java-server</artifactId>
<version>1.0.0rc0</version>
</dependency>
</dependencies>
</project>
It doesn't fetch the jquery or dojo components since that wasn't working. And it doesn't matter for me, since that is hosted separately.
web.xml
Theweb.xml looks like this:<?xml version="1.0" encoding="UTF-8"?>The load-on-startup values indicate the order in which modules are loaded. They must be set so your code loads after the cometd server
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- Request that Jetty create an MBean to manage the Bayeux instance -->
<context-param>
<param-name>org.eclipse.jetty.server.context.ManagedAttributes</param-name>
<param-value>org.cometd.bayeux</param-value>
</context-param>
<!-- Load the cometd service -->
<servlet>
<servlet-name>cometd</servlet-name>
<servlet-class>org.cometd.server.continuation.ContinuationCometdServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>cometd</servlet-name>
<url-pattern>/cometd/*</url-pattern>
</servlet-mapping>
<!-- Load our extension -->
<servlet>
<servlet-name>privatemsg</servlet-name>
<!-- the package name (test.cometd) and class name of the servlet to load -->
<servlet-class>test.cometd.PrivateServlet</servlet-class>
<!-- IMPORTANT!! Must be set to load after conetd -->
<load-on-startup>2</load-on-startup>
</servlet>
</web-app>
PrivateServlet.java
ThePrivateServlet.java looks like this:package test.cometd;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletResponse;
import org.cometd.Bayeux;
import org.cometd.Client;
import org.cometd.Message;
import org.cometd.server.AbstractBayeux;
import org.cometd.server.BayeuxService;
import org.eclipse.jetty.util.log.Log;
public class PrivateServlet extends HttpServlet
{
public PrivateServlet()
{
}
@Override
public void init(ServletConfig config) throws ServletException
{
super.init(config);
//get a reference to the previously instatiated bayeux server
final Bayeux bayeux=(Bayeux)getServletContext().getAttribute(Bayeux.ATTRIBUTE);
if (bayeux==null) {
config.getServletContext().log("No "+Bayeux.ATTRIBUTE+" initialized");
throw new UnavailableException(Bayeux.ATTRIBUTE);
}
//this makes it so the user cannot subscribe to anything,
//limiting the service to direct messages only.
bayeux.setSecurityPolicy(new AbstractBayeux.DefaultPolicy()
{
public boolean canSubscribe(org.cometd.Client client, String channel, org.cometd.Message message)
{
return false;
}
});
new PrivateService(bayeux);
}
/**
* Simple private message system
*/
public static class PrivateService extends BayeuxService
{
public PrivateService(Bayeux bayeux)
{
super(bayeux, "private");
subscribe("/service/sendprivate/*", "directMessage");
}
public Object directMessage(Client source, String channel, Object data, String messageId)
{
Client dest = getBayeux().getClient(channel.substring(21));
if (dest!=null) {
//Log.info("relay "+data+" to "+dest);
send(dest,"/service/recvprivate",data,null);
return "OK";
} else {
//Log.info("DEST NOT FOUND "+channel.substring(21));
return "Failed";
}
}
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
((HttpServletResponse)res).sendError(503);
}
}
Ready to Run
To start the Jetty server, and run with the specified configuration, just type
mvn clean jetty:runthat will automatically download dependencies, compile the java code, and start the server.
To use this Bayeux extension, the javascript on the client side must tell the server what clientid the user has. Then the server, via phomet from PHP or similar, can send a message to "/service/sendprivate/
No comments:
Post a Comment