1

我开发了一个带有 java 富客户端和远程对象持久性服务器的 cayenne 项目。如果我有钱的 cient 连接到部署在本地主机上同一台机器上的 Cayenne-ROP-Server(在 Jetty 上来自 maven 目标,如在 cayenne rop 教程中解释的那样),一切都很好:

ClientConnection clientConnection = new HessianConnection("http://localhost:8080/rop.server   /cayenne-service",
            "cayenne-user", "secret", SHARED_CAYENNE_SESSION_NAME);
DataChannel channel = new ClientChannel(clientConnection);
ObjectContext context = new CayenneContext(channel);
List<Object> someEntities = context.performQuery(allMovies);

如果我将第一行中要连接的 url 更改为非本地主机(ubuntu 上的 Tomcat7),那么一切正常,直到第 4 行:

List<Object> someEntities = context.performQuery(allMovies);

然后我收到错误“没有与请求关联的会话”

这是客户端的完整输出:

Running de.pss.hdlist.client.dataservice.MovieDataServiceCayenneImplTest
Sep 07, 2012 10:21:37 AM org.apache.cayenne.remote.hessian.HessianConnection connect
INFO: Connecting to [cayenne-user:*******@http://comunity-server.hopto.org:8080    /rop.server-3.0.2/cayenne-service] - shared session 'global-cayenne-session'
Sep 07, 2012 10:21:40 AM org.apache.cayenne.remote.hessian.HessianConnection connect
INFO: === Connected, session:  org.apache.cayenne.remote.RemoteSession@12241e[sessionId=C47DD36ACE2A043401C8D0C44D5BD8C3,n    ame=global-cayenne-session] - took 3182 ms.
Sep 07, 2012 10:21:53 AM org.apache.cayenne.remote.BaseConnection sendMessage
INFO: --- Message 0: Bootstrap
Sep 07, 2012 10:21:53 AM org.apache.cayenne.remote.BaseConnection sendMessage
INFO: === Message 0: Bootstrap done - took 406 ms.
Sep 07, 2012 10:21:53 AM org.apache.cayenne.remote.BaseConnection sendMessage
INFO: --- Message 1: Query
Sep 07, 2012 10:21:53 AM org.apache.cayenne.remote.BaseConnection sendMessage
INFO: *** Message error for 1: Query - took 187 ms.

这是 Apache Tomcat 日志的服务器端输出:

WARNING: org.apache.cayenne.remote.service.MissingSessionException: [v.3.0.2 Jun 19 2011 09:29:50] No session associated with request.
org.apache.cayenne.remote.service.MissingSessionException: [v.3.0.2 Jun 19 2011 09:29:50] No session associated with request.
    at    org.apache.cayenne.remote.service.BaseRemoteService.processMessage(BaseRemoteService.java:148)
    at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:180)
    at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:109)
    at com.caucho.hessian.server.HessianServlet.service(HessianServlet.java:396)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:679)

我使用 Apache Cayenne 3.0.2、Apache-Tomcat 7.0.29 和 Java 7 sdk

每个帮助都提前 THX

PS。也许本地 Jetty 服务器以另一种方式处理事情,就像远程 unix 机器上的 Tomcat 服务器一样。

编辑:在 Andrus 在下面的答案中给出提示之后,我添加了一个看起来像这样的 SessionListern:

public class HttpSessionListenerLogImpl implements HttpSessionListener {

private final static Logger LOGGER = Logger.getLogger(HttpSessionListenerLogImpl.class.getName());

@Override
public void sessionCreated(HttpSessionEvent hse) {
    LOGGER.log(Level.SEVERE,
            "!__Session created with ID: " + hse.getSession().getId());
    LOGGER.log(Level.SEVERE, "!__Session created by: " + hse.getSource());
    LOGGER.log(Level.SEVERE, "!__Session Attributes: " + hse.getSession().getAttributeNames());
    LOGGER.log(Level.SEVERE, "!__Session max inactivity: " + hse.getSession().getMaxInactiveInterval());
    LOGGER.log(Level.SEVERE, "!__Session context: " + hse.getSession().getServletContext().getServletContextName());
}

@Override
public void sessionDestroyed(HttpSessionEvent hse) {
    LOGGER.log(Level.SEVERE, "!__Session killed with ID: " + hse.getSession().getId());
    LOGGER.log(Level.SEVERE, "!__Session killed by: " + hse.getSource());
    LOGGER.log(Level.SEVERE, "!__Session Attributes: " + hse.getSession().getAttributeNames());
    LOGGER.log(Level.SEVERE, "!__Session max inactivity: " + hse.getSession().getMaxInactiveInterval());
    LOGGER.log(Level.SEVERE, "!__Session context: " + hse.getSession().getServletContext().getServletContextName());
}

因此,在执行此问题之上的 4 行代码状态时,此侦听器为我提供了以下输出:

Sep 11, 2012 11:06:27 AM de.pss.hdlist.HttpSessionListenerLogImpl sessionCreated
SEVERE: !__Session created with ID: B07648A2A5F0005AF6DF0741D7EF2D21
Sep 11, 2012 11:06:27 AM de.pss.hdlist.HttpSessionListenerLogImpl sessionCreated
SEVERE: !__Session created by: org.apache.catalina.session.StandardSessionFacade@515f9553
Sep 11, 2012 11:06:27 AM de.pss.hdlist.HttpSessionListenerLogImpl sessionCreated
SEVERE: !__Session Attributes: java.util.Collections$2@5a44a5e1
Sep 11, 2012 11:06:27 AM de.pss.hdlist.HttpSessionListenerLogImpl sessionCreated
SEVERE: !__Session max inactivity: 216000
Sep 11, 2012 11:06:27 AM de.pss.hdlist.HttpSessionListenerLogImpl sessionCreated
SEVERE: !__Session context: Cayenne Tutorial
Sep 11, 2012 11:06:27 AM com.caucho.hessian.server.HessianSkeleton invoke
WARNING: org.apache.cayenne.remote.service.MissingSessionException: [v.3.0.2 Jun 19 2011 09:29:50] No session associated with request.
org.apache.cayenne.remote.service.MissingSessionException: [v.3.0.2 Jun 19 2011 09:29:50] No session associated with request.
    at  org.apache.cayenne.remote.service.BaseRemoteService.processMessage(BaseRemoteService.java:148)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at  
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:616)
    at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:180)
    at com.caucho.hessian.server.HessianSkeleton.invoke(HessianSkeleton.java:109)
    at com.caucho.hessian.server.HessianServlet.service(HessianServlet.java:396)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:679)

在这里你可以看到有一个会话被创建并且没有会话被杀死。那么为什么我的代码行中的 ObjectContext

List<Object> someEntities = context.performQuery(allMovies);

确实忽略了会话。在进行查询之前我是否必须明确设置它?客户端访问远程部署的 cayenne 服务器的标准初始化代码是什么。它与 cayenne rop 教程中给出的不同吗?

提前谢谢。

编辑:我升级到 cayenne 3.1B1 希望摆脱这个错误,但同样的情况:“没有会话......”尝试发送查询时。

我还在 localhost 上设置了一个 tomcat 并将其配置为与远程相同。尝试发送查询时出现相同的问题“无会话...”。

因此,localhost 上的 Jetty 是唯一一个从上面获取 4 行初始化代码并为每个后续查询保存会话的码头。所以这是我的问题。这个星球上是否有人曾尝试在 tomcat 上部署 cayenne rop 服务器并成功了?

对于每一个小提示,请提前 THX。

编辑:所以我在本地 tomcat7 上做了一点服务器端调试。

1.Client从上面执行第2行代码:

DataChannel channel = new ClientChannel(clientConnection);

在服务器端,我的会话侦听器被触发并告诉我一个会话已创建,ID 为:B6565298F222294F601B76333DBE4911

2.Client从上面执行第3行:

ObjectContext context = new CayenneContext(channel);

在服务器端,类 org.apache.cayenne.remote.service.HttpRemoteSession 的方法被调用:

/**
 * Returns a ServerSession object that represents Cayenne-related state associated
 * with the current session. If ServerSession hasn't been previously saved, returns
 * null.
 */
@Override
protected ServerSession getServerSession() {
    HttpSession httpSession = getSession(true);
    return (ServerSession) httpSession.getAttribute(SESSION_ATTRIBUTE);
}

此方法的第一行创建了一个新会话。其 ID 为:ECC4A81D6240A1D04DA0A646200C4CE6。这个新会话只包含一个属性:键是“org.apache.cayenne.remote.service.HttpRemoteService.ServerSession”,值是(谁猜到了?)之前在步骤 1 中创建的会话让我感到奇怪的是,我的尽管创建了新会话,但不会触发 serveltListener。

3.Client从上面执行第4行

List<Object> someEntities = context.performQuery(allMovies);

现在在服务器端再次调用 getServerSession() 方法。这次还创建了一个新会话(为什么?)。并且此会话不包含任何属性。所以这行“return (ServerSession) httpSession.getAttribute(SESSION_ATTRIBUTE);” 在方法 getServerSession() 内部返回 null ,这恰好触发了异常“No Session associated with request”。

那么,为什么 cayenne 服务器端会创建 e ne 会话而不使用之前创建的旧会话呢?我是否必须在查询中明确发送会话?

编辑:我在运行上面的四行代码时从 netbeans http-monitor 截屏: http 监控 tomcat 卡宴

4

1 回答 1

1

这是 Cayenne ROP 和较新容器之间的问题:

https://issues.apache.org/jira/browse/CAY-1739

这是一个 Tomcat 解决方案 - 创建包含以下内容的 context.xml 文件,并将其放在 webapp 的 META-INF/ 中:

<Context>
    <Valve className="org.apache.catalina.authenticator.BasicAuthenticator"
        changeSessionIdOnAuthentication="false" />
</Context>
于 2012-09-07T20:06:06.217 回答