jwi*_*mar 6 java tomcat jersey atmosphere
以下实质性更新(2014年10月15日)
==========原帖===================
我有一个使用Atmosphere和Jersey的通知服务webapp.我试图在Linux上的Tomcat中运行它,并遇到了问题.(请注意,在Tomcat-embedded-in-Eclipse中运行时,这样可以正常工作,因此可能是Tomcat配置问题.)
问题是广播消息似乎排队或缓冲,并且在我关闭Tomcat之前实际上没有传送到客户端.那时他们都被客户立刻收到了.
我尝试了很多在各种帖子中找到的东西试图解决这个问题,但是我的努力是分散的,因为我不知道是什么导致了这个问题:
这些都没有改变服务的行为.而且,再次,它似乎在Eclipse中运行时工作正常.
环境:Ubuntu 14.04 LTS.Tomcat 7.0.54.气氛2.1.5.对于客户来说,我现在只是使用telnet.
(这段代码比示例复杂一点,因为我有许多不同的路由我想支持,而且我正在使用这个答案提出的方法,这似乎工作得很好.而且我正在返回通知对象而不是字符串.这似乎也运行正常.为了清楚起见,我已经删除了大部分认证内容.)
pom.xml中:
<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>com.clearcaptial</groupId>
<artifactId>notifications</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>notifications Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-jersey</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.17.1</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime-native</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-compat-jbossweb</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-compat-tomcat</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
<build>
<finalName>notifications</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Run Code Online (Sandbox Code Playgroud)
web.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:j2ee="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3.0.xsd">
<servlet>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.clearcapital.notifications</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>org.atmosphere.useWebSocketAndServlet3</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Run Code Online (Sandbox Code Playgroud)
来自ValidationsRouter.java:
@Path("/validations")
public class ValidationsRouter {
@Context
private AtmosphereResource atmosphereResource;
@GET
public SuspendResponse<ValidationNotification> subscribe(@Context UriInfo uri) throws URISyntaxException, NamingException, IOException {
return new ValidationsResource().subscribe(uri, atmosphereResource);
}
@Broadcast
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Broadcastable broadcast(ValidationNotification message, @Context UriInfo uri) {
return new ValidationsResource().broadcast(message, uri);
}
}
Run Code Online (Sandbox Code Playgroud)
来自ValidationsResource.java:
public class ValidationsResource extends ResourceBase<ValidationNotification> {
// a bunch of authentication stuff omitted for clarity.
}
Run Code Online (Sandbox Code Playgroud)
来自ResourceBase.java:
public abstract class ResourceBase<T> {
public SuspendResponse<T> subscribe(UriInfo uri, AtmosphereResource atmosphereResource) throws URISyntaxException, NamingException, IOException {
Broadcaster myBroadcaster = BroadcasterFactory.getDefault().lookup(uri.getPath(), true);
return new SuspendResponse.SuspendResponseBuilder<T>().broadcaster(myBroadcaster).outputComments(true)
.addListener(new EventsLogger()).type(MediaType.APPLICATION_JSON_TYPE).build();
}
public Broadcastable broadcast(T message, UriInfo uri) {
Broadcaster myBroadcaster = BroadcasterFactory.getDefault().lookup(uri.getPath(), true);
return new Broadcastable(message, "", myBroadcaster);
}
}
Run Code Online (Sandbox Code Playgroud)
============原帖结束======================
2014年10月15日更新:
一段时间后,我又回到了这个问题上.使用新版本的Atmosphere(2.2.3)更新项目后,我发现行为没有区别.仍然如此,当在与客户端运行不同的计算机上运行服务时,在Tomcat关闭之前,客户端不会接收大气广播.在同一台计算机上运行客户端和服务时,一切都按预期工作.
因此,为了确定问题所在,我已经开始在我的测试中使用其中一个Atmosphere示例应用程序.我正在使用jersey-pubsub示例应用程序(稍微更新以使其编译),因为那是最接近我正在尝试的那个.我创建了一个全新的服务器环境来运行示例应用程序,以最小化基于Linux配置的任何变量.以下是新步骤 - 也许有人可以复制行为.
要安装Tomcat7的新服务器(我使用Vagrant和VirtualBox进行这些测试):
host$ vagrant init ubuntu/trusty64
host$ nano Vagrantfile
Run Code Online (Sandbox Code Playgroud)
将网络配置更改为已知IP: config.vm.network :private_network, ip: "10.1.1.2"
host$ vagrant box add https://vagrantcloud.com/ubuntu/boxes/trusty64/versions/1/providers/virtualbox.box
host$ vagrant up
------------------
vagrant$ sudo apt-get update
vagrant$ sudo apt-get upgrade
vagrant$ sudo apt-get install tomcat7
Run Code Online (Sandbox Code Playgroud)
按照这些步骤,我最终得到了Tomcat 7.0.52和Ubuntu 14.04
我有一个我使用的jersey-pubsub项目(没有父项目等)的副本
host$ mvn clean install
Run Code Online (Sandbox Code Playgroud)
然后部署
host$ cp target/jersey-pubsub.war ../../vagrants/trusty64/
vagrant$ sudo cp /vagrant/jersey-pubsub.war /var/lib/tomcat7/webapps
Run Code Online (Sandbox Code Playgroud)
然后我可以使用telnet测试它,例如:
host$ telnet 10.1.1.2 8080 <return>
GET /jersey-pubsub/pubsub/foo HTTP/1.0 <return>
<return>
Run Code Online (Sandbox Code Playgroud)
此时,telnet继续等待数据.在tomcat服务器日志中,我可以看到一个条目:
20:33:55.805 [http-bio-8080-exec-1] INFO o.a.samples.pubsub.EventsLogger - onSuspend(): 10.1.1.1:59357
Run Code Online (Sandbox Code Playgroud)
然后我向服务器发送POST请求.我正在使用POSTman,但我认为这不重要.
POST http://10.1.1.2:8080/jersey-pubsub/pubsub/foo
Accept: text/html
Content-Type: application/x-www-form-urlencoded
message: <html><body><p>This is a test!</p></body></html>
Run Code Online (Sandbox Code Playgroud)
在服务器日志中,我可以看到服务器认为它广播了消息:
20:34:06.990 [Atmosphere-Shared-AsyncOp-0] INFO o.a.samples.pubsub.EventsLogger - onBroadcast(): <html><body><p>This is a test!</p></body></html>
Run Code Online (Sandbox Code Playgroud)
但telnet客户端中没有任何内容.我可以无限重复,看不到任何结果,直到我关闭Tomcat,此时Telnet立即收到所有广播消息.
相反,如果我在主机上运行的tomcat实例上部署服务,或者如果我在vagrant实例中运行telnet,一切都按预期工作:
vagrant$ telnet localhost 8080 <return>
GET /jersey-pubsub/pubsub/foo HTTP/1.0 <return>
<return>
Run Code Online (Sandbox Code Playgroud)
如果我然后发送相同的POST请求,我立即在telnet中收到广播消息.行为似乎是,如果服务和客户端不在同一台计算机上,则在Tomcat运行时会阻止网络流量.
这是我的jersey-pubsub示例副本的源代码,只需进行足够的更改即可将其编译和构建为独立项目.
EventsLogger.java :(不变,除了@Override在2个地方删除让Eclipse停止抱怨)
FileResource.java :(不变)
JerseyPubSub.java :(不变)
web.xml :(不变)
pom.xml(修改为独立构建,不引用父pom):
<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>org.atmosphere.samples</groupId>
<artifactId>atmosphere-jersey-pubsub</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>atmosphere-jersey-pubsub</name>
<url>http://maven.apache.org</url>
<properties>
<atmosphere-version>2.2.3</atmosphere-version>
<client-version>2.2.3</client-version>
<logback-version>1.0.13</logback-version>
</properties>
<repositories>
<repository>
<id>oss.sonatype.org</id>
<url>http://oss.sonatype.org/content/repositories/releases</url>
</repository>
<repository>
<id>oss.sonatype.org-snapshot</id>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
<!-- <repository> <id>scala-tools.org</id> <name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url> </repository> -->
<repository>
<id>jboss</id>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>codehaus</id>
<name>repository.codehaus.org</name>
<url>http://repository.codehaus.org</url>
</repository>
<repository>
<id>codehaus-snapshots</id>
<url>http://snapshots.repository.codehaus.org</url>
</repository>
<repository>
<id>maven.java.net</id>
<url>https://maven.java.net/content/groups/public/</url>
</repository>
</repositories>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
<version>${atmosphere-version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback-version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.atmosphere.client</groupId>
<artifactId>javascript</artifactId>
<version>${client-version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-jersey</artifactId>
<version>${atmosphere-version}</version>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback-version}</version>
</dependency>
</dependencies>
<build>
<finalName>jersey-pubsub</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Run Code Online (Sandbox Code Playgroud)
几个月后回到这个问题后,我能够弄清楚为什么我会看到这种行为:特别是内置的 Mac telnet 客户端表现不佳。我确认在 Windows 或 Linux 上使用 telnet 时会立即记录响应,并且我还使用不同的 Mac telnet 客户端进行了测试,它的行为也符合预期。虽然我使用它有一段时间了,但我无法弄清楚是否有我可以在 Mac 上指定的 telnet 选项,使其表现得与我测试的 Linux 相当。