You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by dk...@apache.org on 2016/03/01 15:50:39 UTC

[1/9] cayenne git commit: Add missing deserializer implementation.

Repository: cayenne
Updated Branches:
  refs/heads/master f72db8b20 -> c2e5d6deb


Add missing deserializer implementation.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/7cfb4c7b
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/7cfb4c7b
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/7cfb4c7b

Branch: refs/heads/master
Commit: 7cfb4c7b01e8fcd8908809b530a5be8169613f21
Parents: 83185f2
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Wed Jan 20 10:29:59 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 12:49:03 2016 +0300

----------------------------------------------------------------------
 .../apache/cayenne/rop/HessianROPSerializationService.java    | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/7cfb4c7b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
index 5b0c9a0..31825ce 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
@@ -55,8 +55,11 @@ public class HessianROPSerializationService implements ROPSerializationService {
 	}
 
 	@Override
-	public <T> T deserialize(byte[] serializedObject, Class<T> objectClass) {
-		return null;
+	public <T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException {
+        HessianInput in = new HessianInput(new ByteArrayInputStream(serializedObject));
+        in.setSerializerFactory(serializerFactory);
+
+        return objectClass.cast(in.readObject());
 	}
 
 	@Override


[3/9] cayenne git commit: Assorted fixes to the new ROP mechanism resolving problems with session not being preserved between requests.

Posted by dk...@apache.org.
Assorted fixes to the new ROP mechanism resolving problems with session not being preserved between requests.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c775dc49
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c775dc49
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c775dc49

Branch: refs/heads/master
Commit: c775dc495f42afa23887af5a0b55f7a13f59cc46
Parents: 7cfb4c7
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Wed Jan 20 14:05:04 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 14:10:14 2016 +0300

----------------------------------------------------------------------
 .../configuration/rop/client/ClientModule.java  |  2 -
 .../remote/hessian/HessianConnection.java       |  1 -
 .../cayenne/rop/DefaultClientConnection.java    |  4 ++
 .../rop/DefaultClientConnectionProvider.java    | 37 ++++++++++-
 .../apache/cayenne/rop/ProxyRemoteService.java  | 35 +++++-----
 .../cayenne/rop/http/HttpROPConnector.java      | 24 +++++++
 .../rop/http/HttpROPConnectorProvider.java      | 58 -----------------
 .../rop/HessianROPSerializationService.java     | 31 ++++-----
 .../cayenne/rop/ROPSerializationService.java    | 12 ++--
 .../java/org/apache/cayenne/rop/ROPServlet.java | 67 ++++++++++++--------
 10 files changed, 140 insertions(+), 131 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
index 041408a..a782ca3 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
@@ -35,7 +35,6 @@ import org.apache.cayenne.remote.ClientConnection;
 import org.apache.cayenne.remote.RemoteService;
 import org.apache.cayenne.rop.*;
 import org.apache.cayenne.rop.http.ClientHessianSerializationServiceProvider;
-import org.apache.cayenne.rop.http.HttpROPConnectorProvider;
 
 /**
  * A DI module containing all Cayenne ROP client runtime configurations.
@@ -61,7 +60,6 @@ public class ClientModule implements Module {
 
         binder.bind(ObjectContextFactory.class).to(CayenneContextFactory.class);
         binder.bind(ROPSerializationService.class).toProvider(ClientHessianSerializationServiceProvider.class);
-        binder.bind(ROPConnector.class).toProvider(HttpROPConnectorProvider.class);
         binder.bind(RemoteService.class).to(ProxyRemoteService.class);
         binder.bind(ClientConnection.class).toProvider(DefaultClientConnectionProvider.class);
         binder.bind(EventManager.class).to(DefaultEventManager.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
index 3bea90d..372cfc7 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
@@ -226,7 +226,6 @@ public class HessianConnection extends BaseConnection {
         factory.setConnectionFactory(new HessianURLConnectionFactory(this));
         factory.setUser(userName);
         factory.setPassword(password);
-//        factory.setReadTimeout(getReadTimeout());
 
         this.serializerFactory = factory.getSerializerFactory();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
index 2004c6e..00f21fc 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
@@ -38,6 +38,10 @@ public class DefaultClientConnection extends BaseConnection {
         this.sharedSessionName = sharedSession;
     }
 
+    public RemoteSession getSession() {
+        return session;
+    }
+
 	@Override
 	protected void beforeSendMessage(ClientMessage message) throws CayenneRuntimeException {
 		if (session == null) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
index a6dc9e5..61ba2d4 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
@@ -18,13 +18,14 @@
  ****************************************************************/
 package org.apache.cayenne.rop;
 
+import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.configuration.Constants;
 import org.apache.cayenne.configuration.RuntimeProperties;
 import org.apache.cayenne.di.DIRuntimeException;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.di.Provider;
 import org.apache.cayenne.remote.ClientConnection;
-import org.apache.cayenne.remote.RemoteService;
+import org.apache.cayenne.rop.http.HttpROPConnector;
 
 public class DefaultClientConnectionProvider implements Provider<ClientConnection> {
 
@@ -32,13 +33,43 @@ public class DefaultClientConnectionProvider implements Provider<ClientConnectio
     protected RuntimeProperties runtimeProperties;
     
     @Inject
-    protected RemoteService remoteService;
+    protected ROPSerializationService serializationService;
 
     @Override
     public ClientConnection get() throws DIRuntimeException {
         String sharedSession = runtimeProperties
                 .get(Constants.ROP_SERVICE_SHARED_SESSION_PROPERTY);
 
-        return new DefaultClientConnection(remoteService, sharedSession);
+        HttpROPConnector ropConnector = createHttpRopConnector();
+        ProxyRemoteService remoteService = new ProxyRemoteService(serializationService, ropConnector);
+
+        DefaultClientConnection clientConnection = new DefaultClientConnection(remoteService, sharedSession);
+        ropConnector.setClientConnection(clientConnection);
+
+        return clientConnection;
+    }
+
+    protected HttpROPConnector createHttpRopConnector() {
+        String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY);
+        if (url == null) {
+            throw new ConfigurationException(
+                    "No property defined for '%s', can't initialize HessianConnection",
+                    Constants.ROP_SERVICE_URL_PROPERTY);
+        }
+
+        String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY);
+        String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY);
+
+        long readTimeout = runtimeProperties.getLong(
+                Constants.ROP_SERVICE_TIMEOUT_PROPERTY,
+                -1L);
+
+        HttpROPConnector result = new HttpROPConnector(url, userName, password);
+
+        if (readTimeout > 0) {
+            result.setReadTimeout(readTimeout);
+        }
+
+        return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java
index ecfb441..57d4650 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java
@@ -28,32 +28,35 @@ import java.rmi.RemoteException;
 
 public class ProxyRemoteService implements RemoteService {
 
-	@Inject
-	protected ROPSerializationService serializationService;
-	
-	@Inject
-	protected ROPConnector ropConnector;
-	
-	@Override
-	public RemoteSession establishSession() throws RemoteException {
+    protected ROPSerializationService serializationService;
+
+    protected ROPConnector ropConnector;
+
+    public ProxyRemoteService(@Inject ROPSerializationService serializationService, @Inject ROPConnector ropConnector) {
+        this.serializationService = serializationService;
+        this.ropConnector = ropConnector;
+    }
+
+    @Override
+    public RemoteSession establishSession() throws RemoteException {
         try {
             return serializationService.deserialize(ropConnector.establishSession(), RemoteSession.class);
         } catch (IOException e) {
             throw new RemoteException(e.getMessage());
         }
-	}
+    }
 
-	@Override
-	public RemoteSession establishSharedSession(String name) throws RemoteException {
+    @Override
+    public RemoteSession establishSharedSession(String name) throws RemoteException {
         try {
             return serializationService.deserialize(ropConnector.establishSharedSession(name), RemoteSession.class);
         } catch (IOException e) {
             throw new RemoteException(e.getMessage());
         }
-	}
+    }
 
-	@Override
-	public Object processMessage(ClientMessage message) throws RemoteException, Throwable {
-		return serializationService.deserialize(ropConnector.sendMessage(serializationService.serialize(message)), Object.class);
-	}
+    @Override
+    public Object processMessage(ClientMessage message) throws RemoteException, Throwable {
+        return serializationService.deserialize(ropConnector.sendMessage(serializationService.serialize(message)), Object.class);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
index 786add2..198ab19 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.rop.http;
 
+import org.apache.cayenne.remote.RemoteSession;
+import org.apache.cayenne.rop.DefaultClientConnection;
 import org.apache.cayenne.rop.ROPConnector;
 import org.apache.cayenne.rop.ROPConstants;
 import org.apache.commons.logging.Log;
@@ -36,6 +38,10 @@ public class HttpROPConnector implements ROPConnector {
 
     private static Log logger = LogFactory.getLog(HttpROPConnector.class);
 
+    public static final String SESSION_COOKIE_NAME = "JSESSIONID";
+
+    private DefaultClientConnection clientConnection;
+
     private String url;
 
     private String username;
@@ -48,6 +54,10 @@ public class HttpROPConnector implements ROPConnector {
         this.username = username;
         this.password = password;
     }
+
+    public void setClientConnection(DefaultClientConnection clientConnection) {
+        this.clientConnection = clientConnection;
+    }
     
     public void setReadTimeout(Long readTimeout) {
         this.readTimeout = readTimeout;
@@ -111,6 +121,7 @@ public class HttpROPConnector implements ROPConnector {
 
 		try (OutputStream output = connection.getOutputStream()) {
 			output.write(urlParams.toString().getBytes(StandardCharsets.UTF_8));
+            output.flush();
 		}
 
 		return connection.getInputStream();
@@ -124,11 +135,15 @@ public class HttpROPConnector implements ROPConnector {
         }
 
         addAuthHeader(connection);
+        addSessionCookie(connection);
         connection.setDoOutput(true);
 
+        connection.setRequestProperty("Content-Type", "application/octet-stream");
+
         if (data != null) {
             try (OutputStream output = connection.getOutputStream()) {
                 output.write(data);
+                output.flush();
             }
         }
 
@@ -143,6 +158,15 @@ public class HttpROPConnector implements ROPConnector {
         }
     }
 
+    protected void addSessionCookie(URLConnection connection) {
+        RemoteSession session = clientConnection.getSession();
+        if (session != null && session.getSessionId() != null) {
+            connection.addRequestProperty("Cookie", SESSION_COOKIE_NAME
+                    + "="
+                    + session.getSessionId());
+        }
+    }
+
     public String getBasicAuth(String user, String password) {
         if (user != null && password != null) {
             return "Basic " + base64(user + ":" + password);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java
deleted file mode 100644
index 919a51f..0000000
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.rop.http;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.di.DIRuntimeException;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Provider;
-import org.apache.cayenne.rop.ROPConnector;
-
-public class HttpROPConnectorProvider implements Provider<ROPConnector> {
-
-    @Inject
-    protected RuntimeProperties runtimeProperties;
-
-    @Override
-    public ROPConnector get() throws DIRuntimeException {
-        String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY);
-        if (url == null) {
-            throw new ConfigurationException(
-                    "No property defined for '%s', can't initialize HessianConnection",
-                    Constants.ROP_SERVICE_URL_PROPERTY);
-        }
-
-        String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY);
-        String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY);
-
-        long readTimeout = runtimeProperties.getLong(
-                Constants.ROP_SERVICE_TIMEOUT_PROPERTY,
-                -1L);
-
-        HttpROPConnector result = new HttpROPConnector(url, userName, password);
-
-        if (readTimeout > 0) {
-            result.setReadTimeout(readTimeout);
-        }
-
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
index 31825ce..af3c656 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
@@ -18,51 +18,48 @@
  ****************************************************************/
 package org.apache.cayenne.rop;
 
-import com.caucho.hessian.io.Hessian2Output;
 import com.caucho.hessian.io.HessianInput;
 import com.caucho.hessian.io.HessianOutput;
 import com.caucho.hessian.io.SerializerFactory;
-import org.apache.cayenne.DataChannel;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.remote.hessian.HessianConfig;
-import org.apache.cayenne.remote.hessian.service.HessianService;
 
 import java.io.*;
 
 public class HessianROPSerializationService implements ROPSerializationService {
 
     protected SerializerFactory serializerFactory;
-    
+
     public HessianROPSerializationService(SerializerFactory serializerFactory) {
         this.serializerFactory = serializerFactory;
     }
-    
+
     @Override
     public byte[] serialize(Object object) throws IOException {
         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
         HessianOutput out = new HessianOutput(bytes);
         out.setSerializerFactory(serializerFactory);
         out.writeObject(object);
+        out.flush();
 
         return bytes.toByteArray();
     }
 
-	@Override
-	public void serialize(Object object, OutputStream outputStream) throws IOException {
-		Hessian2Output out = new Hessian2Output(outputStream);
-		out.setSerializerFactory(serializerFactory);
-		out.writeObject(object);
-	}
+    @Override
+    public void serialize(Object object, OutputStream outputStream) throws IOException {
+        HessianOutput out = new HessianOutput(outputStream);
+        out.setSerializerFactory(serializerFactory);
+        out.writeObject(object);
+        out.flush();
+    }
 
-	@Override
-	public <T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException {
+    @Override
+    public <T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException {
         HessianInput in = new HessianInput(new ByteArrayInputStream(serializedObject));
         in.setSerializerFactory(serializerFactory);
 
         return objectClass.cast(in.readObject());
-	}
+    }
 
-	@Override
+    @Override
     public <T> T deserialize(InputStream input, Class<T> objectClass) throws IOException {
         HessianInput in = new HessianInput(input);
         in.setSerializerFactory(serializerFactory);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java
index 18c8cdb..486b0e9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java
@@ -23,12 +23,12 @@ import java.io.InputStream;
 import java.io.OutputStream;
 
 public interface ROPSerializationService {
-    
+
     byte[] serialize(Object object) throws IOException;
-	
-	void serialize(Object object, OutputStream outputStream) throws IOException;
-    
+
+    void serialize(Object object, OutputStream outputStream) throws IOException;
+
     <T> T deserialize(InputStream inputStream, Class<T> objectClass) throws IOException;
-	
-	<T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException;
+
+    <T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException;
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c775dc49/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java
index db8d5fb..8c12baf 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.rop;
 
+import com.caucho.services.server.ServiceContext;
 import org.apache.cayenne.configuration.CayenneRuntime;
 import org.apache.cayenne.configuration.rop.server.ROPServerModule;
 import org.apache.cayenne.configuration.server.ServerRuntime;
@@ -90,33 +91,43 @@ public class ROPServlet extends HttpServlet {
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 		try {
-			String operation = req.getParameter(ROPConstants.OPERATION_PARAMETER);
-
-			if (operation != null) {
-				switch (operation) {
-					case ROPConstants.ESTABLISH_SESSION_OPERATION:
-						RemoteSession session = remoteService.establishSession();
-						serializationService.serialize(session, resp.getOutputStream());
-						break;
-					case ROPConstants.ESTABLISH_SHARED_SESSION_OPERATION:
-						String sessionName = req.getParameter(ROPConstants.SESSION_NAME_PARAMETER);
-						RemoteSession sharedSession = remoteService.establishSharedSession(sessionName);
-
-						serializationService.serialize(sharedSession, resp.getOutputStream());
-						break;
-					default:
-						throw new ServletException("Unknown operation: " + operation);
-				}
-			} else {
-					Object response = remoteService.processMessage(
-							serializationService.deserialize(req.getInputStream(), ClientMessage.class));
-
-					serializationService.serialize(response, resp.getOutputStream());
-			}
-		} catch (RuntimeException | ServletException e) {
-			throw e;
-		} catch (Throwable e) {
-			throw new ServletException(e);
-		}
+            String serviceId = req.getPathInfo();
+            String objectId = req.getParameter("id");
+
+            if (objectId == null) {
+                objectId = req.getParameter("ejbid");
+            }
+
+            // TODO: need to untangle HttpRemoteService from dependence on Hessian's ServiceContext thread local setup
+            ServiceContext.begin(req, resp, serviceId, objectId);
+
+            String operation = req.getParameter(ROPConstants.OPERATION_PARAMETER);
+
+            if (operation != null) {
+                switch (operation) {
+                    case ROPConstants.ESTABLISH_SESSION_OPERATION:
+                        RemoteSession session = remoteService.establishSession();
+                        serializationService.serialize(session, resp.getOutputStream());
+                        break;
+                    case ROPConstants.ESTABLISH_SHARED_SESSION_OPERATION:
+                        String sessionName = req.getParameter(ROPConstants.SESSION_NAME_PARAMETER);
+                        RemoteSession sharedSession = remoteService.establishSharedSession(sessionName);
+
+                        serializationService.serialize(sharedSession, resp.getOutputStream());
+                        break;
+                    default:
+                        throw new ServletException("Unknown operation: " + operation);
+                }
+            } else {
+                Object response = remoteService.processMessage(
+                        serializationService.deserialize(req.getInputStream(), ClientMessage.class));
+
+                serializationService.serialize(response, resp.getOutputStream());
+            }
+        } catch (RuntimeException | ServletException e) {
+            throw e;
+        } catch (Throwable e) {
+            throw new ServletException(e);
+        }
     }
 }


[9/9] cayenne git commit: CAY-2065 Pluggable serialization and connectivity layers for ROP

Posted by dk...@apache.org.
CAY-2065 Pluggable serialization and connectivity layers for ROP

Merge pull request https://github.com/apache/cayenne/pull/89


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c2e5d6de
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c2e5d6de
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c2e5d6de

Branch: refs/heads/master
Commit: c2e5d6deb4075f949e965fd88c94829595cd6d0a
Parents: f72db8b 2c3719c
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Tue Mar 1 17:29:26 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 17:29:26 2016 +0300

----------------------------------------------------------------------
 .../configuration/rop/client/ClientModule.java  |   7 +-
 .../rop/client/HessianConnectionProvider.java   |  63 ----
 .../apache/cayenne/remote/BaseConnection.java   |  21 --
 .../remote/hessian/ClientSerializerFactory.java |   2 +-
 .../remote/hessian/HessianConnection.java       | 309 -------------------
 .../hessian/HessianURLConnectionFactory.java    |  51 ---
 .../remote/hessian/service/HessianUtil.java     |  11 +-
 .../cayenne/rop/HttpClientConnection.java       | 126 ++++++++
 .../rop/HttpClientConnectionProvider.java       |  75 +++++
 .../apache/cayenne/rop/ProxyRemoteService.java  |  62 ++++
 .../org/apache/cayenne/rop/ROPConnector.java    |  47 +++
 ...ientHessianSerializationServiceProvider.java |  39 +++
 .../cayenne/rop/http/HttpROPConnector.java      | 257 +++++++++++++++
 .../rop/client/ClientModuleTest.java            |   4 +-
 .../remote/hessian/HessianConnectionTest.java   |  81 -----
 .../http/HessianROPSerializationServiceIT.java  |  94 ++++++
 .../rop/server/ROPHessianServlet.java           | 127 --------
 .../rop/server/ROPServerModule.java             |   7 +-
 .../cayenne/configuration/web/WebUtil.java      |   3 +-
 .../apache/cayenne/remote/RemoteService.java    |   2 +-
 .../service/ServerSerializerFactory.java        |   2 +-
 .../rop/HessianROPSerializationService.java     |  69 +++++
 .../org/apache/cayenne/rop/ROPConstants.java    |  28 ++
 .../cayenne/rop/ROPSerializationService.java    |  34 ++
 .../java/org/apache/cayenne/rop/ROPServlet.java | 133 ++++++++
 ...rverHessianSerializationServiceProvider.java |  37 +++
 .../cayenne/rop/ServerHttpRemoteService.java    |  48 +++
 .../rop/server/ROPHessianServletTest.java       | 183 -----------
 .../rop/server/ROPServletTest.java              | 179 +++++++++++
 docs/doc/src/main/resources/UPGRADE.txt         |   4 +
 .../src/main/webapp/WEB-INF/web.xml             |   2 +-
 31 files changed, 1256 insertions(+), 851 deletions(-)
----------------------------------------------------------------------



[2/9] cayenne git commit: Initial implementation of ROP refactoring decoupling Hessian from connectivity layer and introducing pluggable serialization and connectivity layers.

Posted by dk...@apache.org.
Initial implementation of ROP refactoring decoupling Hessian from connectivity layer and introducing pluggable serialization and connectivity layers.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/83185f25
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/83185f25
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/83185f25

Branch: refs/heads/master
Commit: 83185f2558f764cf60b137a2e2eeda47d366a17f
Parents: f72db8b
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Tue Jan 19 01:38:28 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 12:49:03 2016 +0300

----------------------------------------------------------------------
 .../configuration/rop/client/ClientModule.java  |   9 +-
 .../rop/client/HessianConnectionProvider.java   |  63 -----
 .../apache/cayenne/remote/BaseConnection.java   |  21 --
 .../remote/hessian/ClientSerializerFactory.java |   2 +-
 .../remote/hessian/HessianConnection.java       |   2 +-
 .../cayenne/rop/DefaultClientConnection.java    | 122 ++++++++++
 .../rop/DefaultClientConnectionProvider.java    |  44 ++++
 .../apache/cayenne/rop/ProxyRemoteService.java  |  59 +++++
 .../org/apache/cayenne/rop/ROPConnector.java    |  32 +++
 ...ientHessianSerializationServiceProvider.java |  39 ++++
 .../cayenne/rop/http/HttpROPConnector.java      | 233 +++++++++++++++++++
 .../rop/http/HttpROPConnectorProvider.java      |  58 +++++
 .../rop/client/ClientModuleTest.java            |   4 +-
 .../rop/server/ROPServerModule.java             |   7 +-
 .../service/ServerSerializerFactory.java        |   2 +-
 .../rop/HessianROPSerializationService.java     |  69 ++++++
 .../org/apache/cayenne/rop/ROPConstants.java    |  28 +++
 .../cayenne/rop/ROPSerializationService.java    |  34 +++
 .../java/org/apache/cayenne/rop/ROPServlet.java | 122 ++++++++++
 ...rverHessianSerializationServiceProvider.java |  37 +++
 .../cayenne/rop/ServerHttpRemoteService.java    |  48 ++++
 21 files changed, 943 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
index de64f08..041408a 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
@@ -32,6 +32,10 @@ import org.apache.cayenne.di.Module;
 import org.apache.cayenne.event.DefaultEventManager;
 import org.apache.cayenne.event.EventManager;
 import org.apache.cayenne.remote.ClientConnection;
+import org.apache.cayenne.remote.RemoteService;
+import org.apache.cayenne.rop.*;
+import org.apache.cayenne.rop.http.ClientHessianSerializationServiceProvider;
+import org.apache.cayenne.rop.http.HttpROPConnectorProvider;
 
 /**
  * A DI module containing all Cayenne ROP client runtime configurations.
@@ -56,7 +60,10 @@ public class ClientModule implements Module {
         binder.<String> bindMap(Constants.PROPERTIES_MAP).putAll(properties);
 
         binder.bind(ObjectContextFactory.class).to(CayenneContextFactory.class);
-        binder.bind(ClientConnection.class).toProvider(HessianConnectionProvider.class);
+        binder.bind(ROPSerializationService.class).toProvider(ClientHessianSerializationServiceProvider.class);
+        binder.bind(ROPConnector.class).toProvider(HttpROPConnectorProvider.class);
+        binder.bind(RemoteService.class).to(ProxyRemoteService.class);
+        binder.bind(ClientConnection.class).toProvider(DefaultClientConnectionProvider.class);
         binder.bind(EventManager.class).to(DefaultEventManager.class);
         binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
         binder.bind(DataChannel.class).toProvider(ClientChannelProvider.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java
deleted file mode 100644
index 21fda18..0000000
--- a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/HessianConnectionProvider.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.configuration.rop.client;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Provider;
-import org.apache.cayenne.remote.ClientConnection;
-import org.apache.cayenne.remote.hessian.HessianConnection;
-
-public class HessianConnectionProvider implements Provider<ClientConnection> {
-
-    @Inject
-    protected RuntimeProperties runtimeProperties;
-
-    public ClientConnection get() throws ConfigurationException {
-
-        String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY);
-        if (url == null) {
-            throw new ConfigurationException(
-                    "No property defined for '%s', can't initialize HessianConnection",
-                    Constants.ROP_SERVICE_URL_PROPERTY);
-        }
-
-        String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY);
-        String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY);
-        String sharedSession = runtimeProperties
-                .get(Constants.ROP_SERVICE_SHARED_SESSION_PROPERTY);
-        long readTimeout = runtimeProperties.getLong(
-                Constants.ROP_SERVICE_TIMEOUT_PROPERTY,
-                -1l);
-
-        HessianConnection result = new HessianConnection(
-                url,
-                userName,
-                password,
-                sharedSession);
-
-        if (readTimeout > 0) {
-            result.setReadTimeout(readTimeout);
-        }
-
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java
index 74dd3f4..d02449e 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/BaseConnection.java
@@ -33,7 +33,6 @@ public abstract class BaseConnection implements ClientConnection {
 
     protected Log logger;
     protected long messageId;
-    protected long readTimeout = 0L;
     
     /**
      * Default constructor that initializes logging and a single threaded EventManager.
@@ -111,26 +110,6 @@ public abstract class BaseConnection implements ClientConnection {
     public long getProcessedMessagesCount() {
         return messageId + 1;
     }
-
-    /**
-     * The socket timeout on requests in milliseconds. Defaults to infinity.
-     * 
-     * @since 3.1
-     */
-    public long getReadTimeout() {
-        return readTimeout;
-    }
-    
-    /**
-     * Sets the socket timeout.
-     * 
-     * @param readTimeout The socket timeout on requests in milliseconds.
-     * 
-     * @since 3.1
-     */
-    public void setReadTimeout(long readTimeout) {
-        this.readTimeout = readTimeout;
-    }
     
     /**
      * Called before logging the beginning of message processing.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
index f39d642..ff7aeb3 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/ClientSerializerFactory.java
@@ -34,7 +34,7 @@ import com.caucho.hessian.io.Serializer;
  * 
  * @since 1.2
  */
-class ClientSerializerFactory extends AbstractSerializerFactory {
+public class ClientSerializerFactory extends AbstractSerializerFactory {
 
     private Deserializer dataRowDeserializer;
     private Deserializer listDeserializer;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
index d8f6ee2..3bea90d 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
@@ -226,7 +226,7 @@ public class HessianConnection extends BaseConnection {
         factory.setConnectionFactory(new HessianURLConnectionFactory(this));
         factory.setUser(userName);
         factory.setPassword(password);
-        factory.setReadTimeout(getReadTimeout());
+//        factory.setReadTimeout(getReadTimeout());
 
         this.serializerFactory = factory.getSerializerFactory();
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
new file mode 100644
index 0000000..2004c6e
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
@@ -0,0 +1,122 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.event.EventBridge;
+import org.apache.cayenne.event.EventBridgeFactory;
+import org.apache.cayenne.remote.BaseConnection;
+import org.apache.cayenne.remote.ClientMessage;
+import org.apache.cayenne.remote.RemoteService;
+import org.apache.cayenne.remote.RemoteSession;
+
+public class DefaultClientConnection extends BaseConnection {
+
+	private RemoteService remoteService;
+	private RemoteSession session;
+
+	private String sharedSessionName;
+    
+    public DefaultClientConnection(RemoteService remoteService, String sharedSession) {
+        this.remoteService = remoteService;
+        this.sharedSessionName = sharedSession;
+    }
+
+	@Override
+	protected void beforeSendMessage(ClientMessage message) throws CayenneRuntimeException {
+		if (session == null) {
+			connect();
+		}
+	}
+
+	@Override
+	protected Object doSendMessage(ClientMessage message) throws CayenneRuntimeException {
+        try {
+            return remoteService.processMessage(message);
+        }
+        catch (CayenneRuntimeException e) {
+            throw e;
+        }
+        catch (Throwable th) {
+            throw new CayenneRuntimeException(th.getMessage(), th);
+        }
+	}
+
+	@Override
+	public EventBridge getServerEventBridge() throws CayenneRuntimeException {
+        if (session == null) {
+            connect();
+        }
+
+        return createServerEventBridge(session);
+	}
+
+	protected synchronized void connect() {
+		if (session != null) {
+			return;
+		}
+        
+        long t0 = System.currentTimeMillis();
+
+		// create server session...
+		try {
+			this.session = (sharedSessionName != null) ? remoteService
+					.establishSharedSession(sharedSessionName) : remoteService
+					.establishSession();
+		}
+		catch (Throwable th) {
+			logger.info(th.getMessage(), th);
+			throw new CayenneRuntimeException(th.getMessage(), th);
+		}
+
+        if (logger.isInfoEnabled()) {
+            long time = System.currentTimeMillis() - t0;
+            logger.info("=== Connected, session: "
+                    + session
+                    + " - took "
+                    + time
+                    + " ms.");
+        }
+	}
+
+    /**
+     * Creates an EventBridge that will listen for server events. Returns null if server
+     * events support is not configured in the descriptor.
+     *
+     * @throws CayenneRuntimeException if EventBridge startup fails for any reason.
+     */
+    protected EventBridge createServerEventBridge(RemoteSession session) throws CayenneRuntimeException {
+
+        if (!session.isServerEventsEnabled()) {
+            return null;
+        }
+
+        try {
+            EventBridgeFactory factory = (EventBridgeFactory) Class.forName(session.getEventBridgeFactory())
+                    .newInstance();
+
+            // must use "name", not the sessionId as an external subject for the
+            // event bridge
+            return factory.createEventBridge(RemoteSession.getSubjects(), session.getName(),
+                    session.getEventBridgeParameters());
+        } catch (Exception ex) {
+            throw new CayenneRuntimeException("Error creating EventBridge.", ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
new file mode 100644
index 0000000..a6dc9e5
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
@@ -0,0 +1,44 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.remote.ClientConnection;
+import org.apache.cayenne.remote.RemoteService;
+
+public class DefaultClientConnectionProvider implements Provider<ClientConnection> {
+
+    @Inject
+    protected RuntimeProperties runtimeProperties;
+    
+    @Inject
+    protected RemoteService remoteService;
+
+    @Override
+    public ClientConnection get() throws DIRuntimeException {
+        String sharedSession = runtimeProperties
+                .get(Constants.ROP_SERVICE_SHARED_SESSION_PROPERTY);
+
+        return new DefaultClientConnection(remoteService, sharedSession);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java
new file mode 100644
index 0000000..ecfb441
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/ProxyRemoteService.java
@@ -0,0 +1,59 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.remote.ClientMessage;
+import org.apache.cayenne.remote.RemoteService;
+import org.apache.cayenne.remote.RemoteSession;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+
+public class ProxyRemoteService implements RemoteService {
+
+	@Inject
+	protected ROPSerializationService serializationService;
+	
+	@Inject
+	protected ROPConnector ropConnector;
+	
+	@Override
+	public RemoteSession establishSession() throws RemoteException {
+        try {
+            return serializationService.deserialize(ropConnector.establishSession(), RemoteSession.class);
+        } catch (IOException e) {
+            throw new RemoteException(e.getMessage());
+        }
+	}
+
+	@Override
+	public RemoteSession establishSharedSession(String name) throws RemoteException {
+        try {
+            return serializationService.deserialize(ropConnector.establishSharedSession(name), RemoteSession.class);
+        } catch (IOException e) {
+            throw new RemoteException(e.getMessage());
+        }
+	}
+
+	@Override
+	public Object processMessage(ClientMessage message) throws RemoteException, Throwable {
+		return serializationService.deserialize(ropConnector.sendMessage(serializationService.serialize(message)), Object.class);
+	}
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java
new file mode 100644
index 0000000..4976d80
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java
@@ -0,0 +1,32 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public interface ROPConnector {
+
+    InputStream establishSession() throws IOException;
+
+    InputStream establishSharedSession(String name) throws IOException;
+
+    InputStream sendMessage(byte[] message) throws IOException;
+    
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java
new file mode 100644
index 0000000..ecf9339
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/ClientHessianSerializationServiceProvider.java
@@ -0,0 +1,39 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop.http;
+
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.remote.hessian.ClientSerializerFactory;
+import org.apache.cayenne.remote.hessian.HessianConfig;
+import org.apache.cayenne.rop.HessianROPSerializationService;
+import org.apache.cayenne.rop.ROPSerializationService;
+
+public class ClientHessianSerializationServiceProvider implements Provider<ROPSerializationService> {
+
+    public static final String[] CLIENT_SERIALIZER_FACTORIES = new String[] {
+            ClientSerializerFactory.class.getName()
+    };
+
+    @Override
+    public ROPSerializationService get() throws DIRuntimeException {
+        return new HessianROPSerializationService(
+                HessianConfig.createFactory(CLIENT_SERIALIZER_FACTORIES, null));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
new file mode 100644
index 0000000..786add2
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
@@ -0,0 +1,233 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop.http;
+
+import org.apache.cayenne.rop.ROPConnector;
+import org.apache.cayenne.rop.ROPConstants;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpROPConnector implements ROPConnector {
+
+    private static Log logger = LogFactory.getLog(HttpROPConnector.class);
+
+    private String url;
+
+    private String username;
+    private String password;
+
+    private Long readTimeout;
+    
+    public HttpROPConnector(String url, String username, String password) {
+        this.url = url;
+        this.username = username;
+        this.password = password;
+    }
+    
+    public void setReadTimeout(Long readTimeout) {
+        this.readTimeout = readTimeout;
+    }
+
+    @Override
+    public InputStream establishSession() throws IOException {
+        if (logger.isInfoEnabled()) {
+            logConnect(null);
+        }
+		
+		Map<String, String> requestParams = new HashMap<>();
+		requestParams.put(ROPConstants.OPERATION_PARAMETER, ROPConstants.ESTABLISH_SESSION_OPERATION);
+		
+        return doRequest(requestParams);
+    }
+
+    @Override
+    public InputStream establishSharedSession(String name) throws IOException {
+        if (logger.isInfoEnabled()) {
+            logConnect(name);
+        }
+
+		Map<String, String> requestParams = new HashMap<>();
+		requestParams.put(ROPConstants.OPERATION_PARAMETER, ROPConstants.ESTABLISH_SHARED_SESSION_OPERATION);
+		requestParams.put(ROPConstants.SESSION_NAME_PARAMETER, name);
+
+		return doRequest(requestParams);
+    }
+
+    @Override
+    public InputStream sendMessage(byte[] message) throws IOException {
+        return doRequest(message);
+    }
+	
+	protected InputStream doRequest(Map<String, String> params) throws IOException {
+		URLConnection connection = new URL(url).openConnection();
+
+		StringBuilder urlParams = new StringBuilder();
+
+		for (Map.Entry<String, String> entry : params.entrySet()) {
+			if (urlParams.length() > 0) {
+				urlParams.append('&');
+			}
+
+			urlParams.append(entry.getKey());
+			urlParams.append('=');
+			urlParams.append(entry.getValue());
+		}
+
+		if (readTimeout != null) {
+			connection.setReadTimeout(readTimeout.intValue());
+		}
+
+		addAuthHeader(connection);
+
+		connection.setDoOutput(true);
+		
+		connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+		connection.setRequestProperty("charset", "utf-8");
+
+		try (OutputStream output = connection.getOutputStream()) {
+			output.write(urlParams.toString().getBytes(StandardCharsets.UTF_8));
+		}
+
+		return connection.getInputStream();
+	} 
+
+    protected InputStream doRequest(byte[] data) throws IOException {
+        URLConnection connection = new URL(url).openConnection();
+
+        if (readTimeout != null) {
+            connection.setReadTimeout(readTimeout.intValue());
+        }
+
+        addAuthHeader(connection);
+        connection.setDoOutput(true);
+
+        if (data != null) {
+            try (OutputStream output = connection.getOutputStream()) {
+                output.write(data);
+            }
+        }
+
+        return connection.getInputStream();
+    }
+
+    protected void addAuthHeader(URLConnection connection) {
+        String basicAuth = getBasicAuth(username, password);
+
+        if (basicAuth != null) {
+            connection.addRequestProperty("Authorization", basicAuth);
+        }
+    }
+
+    public String getBasicAuth(String user, String password) {
+        if (user != null && password != null) {
+            return "Basic " + base64(user + ":" + password);
+        }
+
+        return null;
+    }
+
+    /**
+     * Creates the Base64 value.
+     */
+    private String base64(String value) {
+        StringBuffer cb = new StringBuffer();
+
+        int i = 0;
+        for (i = 0; i + 2 < value.length(); i += 3) {
+            long chunk = (int) value.charAt(i);
+            chunk = (chunk << 8) + (int) value.charAt(i + 1);
+            chunk = (chunk << 8) + (int) value.charAt(i + 2);
+
+            cb.append(encode(chunk >> 18));
+            cb.append(encode(chunk >> 12));
+            cb.append(encode(chunk >> 6));
+            cb.append(encode(chunk));
+        }
+
+        if (i + 1 < value.length()) {
+            long chunk = (int) value.charAt(i);
+            chunk = (chunk << 8) + (int) value.charAt(i + 1);
+            chunk <<= 8;
+
+            cb.append(encode(chunk >> 18));
+            cb.append(encode(chunk >> 12));
+            cb.append(encode(chunk >> 6));
+            cb.append('=');
+        }
+        else if (i < value.length()) {
+            long chunk = (int) value.charAt(i);
+            chunk <<= 16;
+
+            cb.append(encode(chunk >> 18));
+            cb.append(encode(chunk >> 12));
+            cb.append('=');
+            cb.append('=');
+        }
+
+        return cb.toString();
+    }
+
+    public static char encode(long d) {
+        d &= 0x3f;
+        if (d < 26)
+            return (char) (d + 'A');
+        else if (d < 52)
+            return (char) (d + 'a' - 26);
+        else if (d < 62)
+            return (char) (d + '0' - 52);
+        else if (d == 62)
+            return '+';
+        else
+            return '/';
+    }
+
+    private void logConnect(String sharedSessionName) {
+        StringBuilder log = new StringBuilder("Connecting to [");
+        if (username != null) {
+            log.append(username);
+
+            if (password != null) {
+                log.append(":*******");
+            }
+
+            log.append("@");
+        }
+
+        log.append(url);
+        log.append("]");
+
+        if (sharedSessionName != null) {
+            log.append(" - shared session '").append(sharedSessionName).append("'");
+        }
+        else {
+            log.append(" - dedicated session.");
+        }
+
+        logger.info(log.toString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java
new file mode 100644
index 0000000..919a51f
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnectorProvider.java
@@ -0,0 +1,58 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop.http;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.rop.ROPConnector;
+
+public class HttpROPConnectorProvider implements Provider<ROPConnector> {
+
+    @Inject
+    protected RuntimeProperties runtimeProperties;
+
+    @Override
+    public ROPConnector get() throws DIRuntimeException {
+        String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY);
+        if (url == null) {
+            throw new ConfigurationException(
+                    "No property defined for '%s', can't initialize HessianConnection",
+                    Constants.ROP_SERVICE_URL_PROPERTY);
+        }
+
+        String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY);
+        String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY);
+
+        long readTimeout = runtimeProperties.getLong(
+                Constants.ROP_SERVICE_TIMEOUT_PROPERTY,
+                -1L);
+
+        HttpROPConnector result = new HttpROPConnector(url, userName, password);
+
+        if (readTimeout > 0) {
+            result.setReadTimeout(readTimeout);
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java b/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
index 03d0ad6..836507b 100644
--- a/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
+++ b/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
@@ -28,7 +28,7 @@ import org.apache.cayenne.event.DefaultEventManager;
 import org.apache.cayenne.remote.ClientChannel;
 import org.apache.cayenne.remote.ClientConnection;
 import org.apache.cayenne.remote.MockClientConnection;
-import org.apache.cayenne.remote.hessian.HessianConnection;
+import org.apache.cayenne.rop.DefaultClientConnection;
 import org.junit.Test;
 
 import java.util.HashMap;
@@ -52,7 +52,7 @@ public class ClientModuleTest {
 
         ClientConnection connection = injector.getInstance(ClientConnection.class);
         assertNotNull(connection);
-        assertTrue(connection instanceof HessianConnection);
+        assertTrue(connection instanceof DefaultClientConnection);
 
         assertSame("Connection must be a singleton", connection, injector
                 .getInstance(ClientConnection.class));

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
index 6c9a7ea..ceefd62 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPServerModule.java
@@ -25,7 +25,9 @@ import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.MapBuilder;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.remote.RemoteService;
-import org.apache.cayenne.remote.hessian.service.HessianService;
+import org.apache.cayenne.rop.ServerHessianSerializationServiceProvider;
+import org.apache.cayenne.rop.ServerHttpRemoteService;
+import org.apache.cayenne.rop.ROPSerializationService;
 
 /**
  * A DI module that defines services for the server-side of an ROP application based on
@@ -47,7 +49,8 @@ public class ROPServerModule implements Module {
                 .bindMap(Constants.SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP);
         mapBuilder.putAll(eventBridgeProperties);
 
-        binder.bind(RemoteService.class).to(HessianService.class);
+        binder.bind(RemoteService.class).to(ServerHttpRemoteService.class);
+		binder.bind(ROPSerializationService.class).toProvider(ServerHessianSerializationServiceProvider.class);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java
index 3097e36e..3310cee 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/remote/hessian/service/ServerSerializerFactory.java
@@ -34,7 +34,7 @@ import com.caucho.hessian.io.Serializer;
  * 
  * @since 1.2
  */
-class ServerSerializerFactory extends AbstractSerializerFactory {
+public class ServerSerializerFactory extends AbstractSerializerFactory {
     private ServerPersistentObjectListSerializer persistentObjectListSerializer;
     private ServerDataRowSerializer dataRowSerilaizer;
     private Serializer javaSerializer;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
new file mode 100644
index 0000000..5b0c9a0
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/HessianROPSerializationService.java
@@ -0,0 +1,69 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import com.caucho.hessian.io.Hessian2Output;
+import com.caucho.hessian.io.HessianInput;
+import com.caucho.hessian.io.HessianOutput;
+import com.caucho.hessian.io.SerializerFactory;
+import org.apache.cayenne.DataChannel;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.remote.hessian.HessianConfig;
+import org.apache.cayenne.remote.hessian.service.HessianService;
+
+import java.io.*;
+
+public class HessianROPSerializationService implements ROPSerializationService {
+
+    protected SerializerFactory serializerFactory;
+    
+    public HessianROPSerializationService(SerializerFactory serializerFactory) {
+        this.serializerFactory = serializerFactory;
+    }
+    
+    @Override
+    public byte[] serialize(Object object) throws IOException {
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        HessianOutput out = new HessianOutput(bytes);
+        out.setSerializerFactory(serializerFactory);
+        out.writeObject(object);
+
+        return bytes.toByteArray();
+    }
+
+	@Override
+	public void serialize(Object object, OutputStream outputStream) throws IOException {
+		Hessian2Output out = new Hessian2Output(outputStream);
+		out.setSerializerFactory(serializerFactory);
+		out.writeObject(object);
+	}
+
+	@Override
+	public <T> T deserialize(byte[] serializedObject, Class<T> objectClass) {
+		return null;
+	}
+
+	@Override
+    public <T> T deserialize(InputStream input, Class<T> objectClass) throws IOException {
+        HessianInput in = new HessianInput(input);
+        in.setSerializerFactory(serializerFactory);
+
+        return objectClass.cast(in.readObject());
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java
new file mode 100644
index 0000000..e076eee
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPConstants.java
@@ -0,0 +1,28 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+public class ROPConstants {
+
+    public static final String OPERATION_PARAMETER = "operation";
+    public static final String SESSION_NAME_PARAMETER = "session_name";
+
+    public static final String ESTABLISH_SESSION_OPERATION = "establish_session";
+    public static final String ESTABLISH_SHARED_SESSION_OPERATION = "establish_shared_session";
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java
new file mode 100644
index 0000000..18c8cdb
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPSerializationService.java
@@ -0,0 +1,34 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public interface ROPSerializationService {
+    
+    byte[] serialize(Object object) throws IOException;
+	
+	void serialize(Object object, OutputStream outputStream) throws IOException;
+    
+    <T> T deserialize(InputStream inputStream, Class<T> objectClass) throws IOException;
+	
+	<T> T deserialize(byte[] serializedObject, Class<T> objectClass) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java
new file mode 100644
index 0000000..db8d5fb
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ROPServlet.java
@@ -0,0 +1,122 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import org.apache.cayenne.configuration.CayenneRuntime;
+import org.apache.cayenne.configuration.rop.server.ROPServerModule;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.configuration.web.WebConfiguration;
+import org.apache.cayenne.configuration.web.WebUtil;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.remote.ClientMessage;
+import org.apache.cayenne.remote.RemoteService;
+import org.apache.cayenne.remote.RemoteSession;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+public class ROPServlet extends HttpServlet {
+
+    protected ServletContext servletContext;
+	protected RemoteService remoteService;
+    protected ROPSerializationService serializationService;
+
+    @Override
+    public void init(ServletConfig configuration) throws ServletException {
+
+        checkAlreadyConfigured(configuration.getServletContext());
+
+        this.servletContext = configuration.getServletContext();
+
+        WebConfiguration configAdapter = new WebConfiguration(configuration);
+
+        String configurationLocation = configAdapter.getConfigurationLocation();
+        Map<String, String> eventBridgeParameters = configAdapter.getOtherParameters();
+
+        Collection<Module> modules = configAdapter.createModules(new ROPServerModule(
+                eventBridgeParameters));
+
+        ServerRuntime runtime = new ServerRuntime(configurationLocation, modules
+                .toArray(new Module[modules.size()]));
+
+        this.remoteService = runtime.getInjector().getInstance(RemoteService.class);
+        this.serializationService = runtime.getInjector().getInstance(ROPSerializationService.class);
+
+        WebUtil.setCayenneRuntime(servletContext, runtime);
+        super.init(configuration);
+    }
+
+    protected void checkAlreadyConfigured(ServletContext context) throws ServletException {
+        // sanity check
+        if (WebUtil.getCayenneRuntime(context) != null) {
+            throw new ServletException(
+                    "CayenneRuntime is already configured in the servlet environment");
+        }
+    }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+
+        CayenneRuntime runtime = WebUtil.getCayenneRuntime(servletContext);
+        if (runtime != null) {
+            runtime.shutdown();
+        }
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+		try {
+			String operation = req.getParameter(ROPConstants.OPERATION_PARAMETER);
+
+			if (operation != null) {
+				switch (operation) {
+					case ROPConstants.ESTABLISH_SESSION_OPERATION:
+						RemoteSession session = remoteService.establishSession();
+						serializationService.serialize(session, resp.getOutputStream());
+						break;
+					case ROPConstants.ESTABLISH_SHARED_SESSION_OPERATION:
+						String sessionName = req.getParameter(ROPConstants.SESSION_NAME_PARAMETER);
+						RemoteSession sharedSession = remoteService.establishSharedSession(sessionName);
+
+						serializationService.serialize(sharedSession, resp.getOutputStream());
+						break;
+					default:
+						throw new ServletException("Unknown operation: " + operation);
+				}
+			} else {
+					Object response = remoteService.processMessage(
+							serializationService.deserialize(req.getInputStream(), ClientMessage.class));
+
+					serializationService.serialize(response, resp.getOutputStream());
+			}
+		} catch (RuntimeException | ServletException e) {
+			throw e;
+		} catch (Throwable e) {
+			throw new ServletException(e);
+		}
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java
new file mode 100644
index 0000000..ec0c21c
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHessianSerializationServiceProvider.java
@@ -0,0 +1,37 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.remote.hessian.HessianConfig;
+import org.apache.cayenne.remote.hessian.service.ServerSerializerFactory;
+
+public class ServerHessianSerializationServiceProvider implements Provider<ROPSerializationService> {
+
+    public static final String[] SERVER_SERIALIZER_FACTORIES = new String[] {
+            ServerSerializerFactory.class.getName()
+    };
+
+    @Override
+    public ROPSerializationService get() throws DIRuntimeException {
+        return new HessianROPSerializationService(
+                HessianConfig.createFactory(SERVER_SERIALIZER_FACTORIES, null));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/83185f25/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java
new file mode 100644
index 0000000..22aba9f
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/rop/ServerHttpRemoteService.java
@@ -0,0 +1,48 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import com.caucho.services.server.ServiceContext;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.ObjectContextFactory;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.remote.service.HttpRemoteService;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.util.Map;
+
+public class ServerHttpRemoteService extends HttpRemoteService {
+	
+	public ServerHttpRemoteService(@Inject ObjectContextFactory contextFactory,
+								   @Inject(Constants.SERVER_ROP_EVENT_BRIDGE_PROPERTIES_MAP) Map<String, String> eventBridgeProperties) {
+		super(contextFactory, eventBridgeProperties);
+	}
+
+	@Override
+	protected HttpSession getSession(boolean create) {
+		HttpServletRequest request = (HttpServletRequest) ServiceContext.getContextRequest();
+		if (request == null) {
+			throw new IllegalStateException(
+					"Attempt to access HttpSession outside the request scope.");
+		}
+
+		return request.getSession(create);
+	}
+}


[5/9] cayenne git commit: Switch ROP tutorial to use new ROPServlet class.

Posted by dk...@apache.org.
Switch ROP tutorial to use new ROPServlet class.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/0e13274c
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/0e13274c
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/0e13274c

Branch: refs/heads/master
Commit: 0e13274ceae2733ceec963863633a897514c39e5
Parents: d96ddec
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Tue Mar 1 13:26:49 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 14:10:20 2016 +0300

----------------------------------------------------------------------
 .../src/main/java/org/apache/cayenne/remote/RemoteService.java     | 2 +-
 tutorials/tutorial-rop-server/src/main/webapp/WEB-INF/web.xml      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e13274c/cayenne-server/src/main/java/org/apache/cayenne/remote/RemoteService.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/remote/RemoteService.java b/cayenne-server/src/main/java/org/apache/cayenne/remote/RemoteService.java
index 1baa4cd..b5efb89 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/remote/RemoteService.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/remote/RemoteService.java
@@ -26,7 +26,7 @@ import java.rmi.RemoteException;
  * Interface of a Cayenne remote service.
  * 
  * @since 1.2
- * @see org.apache.cayenne.configuration.rop.server.ROPHessianServlet
+ * @see org.apache.cayenne.rop.ROPServlet
  */
 public interface RemoteService extends Remote {
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e13274c/tutorials/tutorial-rop-server/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/tutorials/tutorial-rop-server/src/main/webapp/WEB-INF/web.xml b/tutorials/tutorial-rop-server/src/main/webapp/WEB-INF/web.xml
index 5f686bc..951d2ca 100644
--- a/tutorials/tutorial-rop-server/src/main/webapp/WEB-INF/web.xml
+++ b/tutorials/tutorial-rop-server/src/main/webapp/WEB-INF/web.xml
@@ -24,7 +24,7 @@
 	<display-name>Cayenne Tutorial</display-name>
 	<servlet>
 		<servlet-name>cayenne-project</servlet-name>
-		<servlet-class>org.apache.cayenne.configuration.rop.server.ROPHessianServlet</servlet-class>
+		<servlet-class>org.apache.cayenne.rop.ROPServlet</servlet-class>
 		<load-on-startup>0</load-on-startup>
 	</servlet>
 	<servlet-mapping>


[4/9] cayenne git commit: Rename DefaultClientConnection to HttpClientConnection, which is more informative.

Posted by dk...@apache.org.
Rename DefaultClientConnection to HttpClientConnection, which is more informative.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/fadd1d1e
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/fadd1d1e
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/fadd1d1e

Branch: refs/heads/master
Commit: fadd1d1e73d883f949f4676f15a37cbe44a30ed1
Parents: c775dc4
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Sun Jan 24 23:26:19 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 14:10:19 2016 +0300

----------------------------------------------------------------------
 .../configuration/rop/client/ClientModule.java  |   2 +-
 .../cayenne/rop/DefaultClientConnection.java    | 126 -------------------
 .../rop/DefaultClientConnectionProvider.java    |  75 -----------
 .../cayenne/rop/HttpClientConnection.java       | 126 +++++++++++++++++++
 .../rop/HttpClientConnectionProvider.java       |  75 +++++++++++
 .../cayenne/rop/http/HttpROPConnector.java      |   6 +-
 .../rop/client/ClientModuleTest.java            |   4 +-
 7 files changed, 207 insertions(+), 207 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/fadd1d1e/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
index a782ca3..b74d482 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/configuration/rop/client/ClientModule.java
@@ -61,7 +61,7 @@ public class ClientModule implements Module {
         binder.bind(ObjectContextFactory.class).to(CayenneContextFactory.class);
         binder.bind(ROPSerializationService.class).toProvider(ClientHessianSerializationServiceProvider.class);
         binder.bind(RemoteService.class).to(ProxyRemoteService.class);
-        binder.bind(ClientConnection.class).toProvider(DefaultClientConnectionProvider.class);
+        binder.bind(ClientConnection.class).toProvider(HttpClientConnectionProvider.class);
         binder.bind(EventManager.class).to(DefaultEventManager.class);
         binder.bind(RuntimeProperties.class).to(DefaultRuntimeProperties.class);
         binder.bind(DataChannel.class).toProvider(ClientChannelProvider.class);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fadd1d1e/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
deleted file mode 100644
index 00f21fc..0000000
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnection.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.rop;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.event.EventBridge;
-import org.apache.cayenne.event.EventBridgeFactory;
-import org.apache.cayenne.remote.BaseConnection;
-import org.apache.cayenne.remote.ClientMessage;
-import org.apache.cayenne.remote.RemoteService;
-import org.apache.cayenne.remote.RemoteSession;
-
-public class DefaultClientConnection extends BaseConnection {
-
-	private RemoteService remoteService;
-	private RemoteSession session;
-
-	private String sharedSessionName;
-    
-    public DefaultClientConnection(RemoteService remoteService, String sharedSession) {
-        this.remoteService = remoteService;
-        this.sharedSessionName = sharedSession;
-    }
-
-    public RemoteSession getSession() {
-        return session;
-    }
-
-	@Override
-	protected void beforeSendMessage(ClientMessage message) throws CayenneRuntimeException {
-		if (session == null) {
-			connect();
-		}
-	}
-
-	@Override
-	protected Object doSendMessage(ClientMessage message) throws CayenneRuntimeException {
-        try {
-            return remoteService.processMessage(message);
-        }
-        catch (CayenneRuntimeException e) {
-            throw e;
-        }
-        catch (Throwable th) {
-            throw new CayenneRuntimeException(th.getMessage(), th);
-        }
-	}
-
-	@Override
-	public EventBridge getServerEventBridge() throws CayenneRuntimeException {
-        if (session == null) {
-            connect();
-        }
-
-        return createServerEventBridge(session);
-	}
-
-	protected synchronized void connect() {
-		if (session != null) {
-			return;
-		}
-        
-        long t0 = System.currentTimeMillis();
-
-		// create server session...
-		try {
-			this.session = (sharedSessionName != null) ? remoteService
-					.establishSharedSession(sharedSessionName) : remoteService
-					.establishSession();
-		}
-		catch (Throwable th) {
-			logger.info(th.getMessage(), th);
-			throw new CayenneRuntimeException(th.getMessage(), th);
-		}
-
-        if (logger.isInfoEnabled()) {
-            long time = System.currentTimeMillis() - t0;
-            logger.info("=== Connected, session: "
-                    + session
-                    + " - took "
-                    + time
-                    + " ms.");
-        }
-	}
-
-    /**
-     * Creates an EventBridge that will listen for server events. Returns null if server
-     * events support is not configured in the descriptor.
-     *
-     * @throws CayenneRuntimeException if EventBridge startup fails for any reason.
-     */
-    protected EventBridge createServerEventBridge(RemoteSession session) throws CayenneRuntimeException {
-
-        if (!session.isServerEventsEnabled()) {
-            return null;
-        }
-
-        try {
-            EventBridgeFactory factory = (EventBridgeFactory) Class.forName(session.getEventBridgeFactory())
-                    .newInstance();
-
-            // must use "name", not the sessionId as an external subject for the
-            // event bridge
-            return factory.createEventBridge(RemoteSession.getSubjects(), session.getName(),
-                    session.getEventBridgeParameters());
-        } catch (Exception ex) {
-            throw new CayenneRuntimeException("Error creating EventBridge.", ex);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fadd1d1e/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
deleted file mode 100644
index 61ba2d4..0000000
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/DefaultClientConnectionProvider.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.rop;
-
-import org.apache.cayenne.ConfigurationException;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.RuntimeProperties;
-import org.apache.cayenne.di.DIRuntimeException;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.di.Provider;
-import org.apache.cayenne.remote.ClientConnection;
-import org.apache.cayenne.rop.http.HttpROPConnector;
-
-public class DefaultClientConnectionProvider implements Provider<ClientConnection> {
-
-    @Inject
-    protected RuntimeProperties runtimeProperties;
-    
-    @Inject
-    protected ROPSerializationService serializationService;
-
-    @Override
-    public ClientConnection get() throws DIRuntimeException {
-        String sharedSession = runtimeProperties
-                .get(Constants.ROP_SERVICE_SHARED_SESSION_PROPERTY);
-
-        HttpROPConnector ropConnector = createHttpRopConnector();
-        ProxyRemoteService remoteService = new ProxyRemoteService(serializationService, ropConnector);
-
-        DefaultClientConnection clientConnection = new DefaultClientConnection(remoteService, sharedSession);
-        ropConnector.setClientConnection(clientConnection);
-
-        return clientConnection;
-    }
-
-    protected HttpROPConnector createHttpRopConnector() {
-        String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY);
-        if (url == null) {
-            throw new ConfigurationException(
-                    "No property defined for '%s', can't initialize HessianConnection",
-                    Constants.ROP_SERVICE_URL_PROPERTY);
-        }
-
-        String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY);
-        String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY);
-
-        long readTimeout = runtimeProperties.getLong(
-                Constants.ROP_SERVICE_TIMEOUT_PROPERTY,
-                -1L);
-
-        HttpROPConnector result = new HttpROPConnector(url, userName, password);
-
-        if (readTimeout > 0) {
-            result.setReadTimeout(readTimeout);
-        }
-
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fadd1d1e/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnection.java
new file mode 100644
index 0000000..06b842c
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnection.java
@@ -0,0 +1,126 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.event.EventBridge;
+import org.apache.cayenne.event.EventBridgeFactory;
+import org.apache.cayenne.remote.BaseConnection;
+import org.apache.cayenne.remote.ClientMessage;
+import org.apache.cayenne.remote.RemoteService;
+import org.apache.cayenne.remote.RemoteSession;
+
+public class HttpClientConnection extends BaseConnection {
+
+	private RemoteService remoteService;
+	private RemoteSession session;
+
+	private String sharedSessionName;
+    
+    public HttpClientConnection(RemoteService remoteService, String sharedSession) {
+        this.remoteService = remoteService;
+        this.sharedSessionName = sharedSession;
+    }
+
+    public RemoteSession getSession() {
+        return session;
+    }
+
+	@Override
+	protected void beforeSendMessage(ClientMessage message) throws CayenneRuntimeException {
+		if (session == null) {
+			connect();
+		}
+	}
+
+	@Override
+	protected Object doSendMessage(ClientMessage message) throws CayenneRuntimeException {
+        try {
+            return remoteService.processMessage(message);
+        }
+        catch (CayenneRuntimeException e) {
+            throw e;
+        }
+        catch (Throwable th) {
+            throw new CayenneRuntimeException(th.getMessage(), th);
+        }
+	}
+
+	@Override
+	public EventBridge getServerEventBridge() throws CayenneRuntimeException {
+        if (session == null) {
+            connect();
+        }
+
+        return createServerEventBridge(session);
+	}
+
+	protected synchronized void connect() {
+		if (session != null) {
+			return;
+		}
+        
+        long t0 = System.currentTimeMillis();
+
+		// create server session...
+		try {
+			this.session = (sharedSessionName != null) ? remoteService
+					.establishSharedSession(sharedSessionName) : remoteService
+					.establishSession();
+		}
+		catch (Throwable th) {
+			logger.info(th.getMessage(), th);
+			throw new CayenneRuntimeException(th.getMessage(), th);
+		}
+
+        if (logger.isInfoEnabled()) {
+            long time = System.currentTimeMillis() - t0;
+            logger.info("=== Connected, session: "
+                    + session
+                    + " - took "
+                    + time
+                    + " ms.");
+        }
+	}
+
+    /**
+     * Creates an EventBridge that will listen for server events. Returns null if server
+     * events support is not configured in the descriptor.
+     *
+     * @throws CayenneRuntimeException if EventBridge startup fails for any reason.
+     */
+    protected EventBridge createServerEventBridge(RemoteSession session) throws CayenneRuntimeException {
+
+        if (!session.isServerEventsEnabled()) {
+            return null;
+        }
+
+        try {
+            EventBridgeFactory factory = (EventBridgeFactory) Class.forName(session.getEventBridgeFactory())
+                    .newInstance();
+
+            // must use "name", not the sessionId as an external subject for the
+            // event bridge
+            return factory.createEventBridge(RemoteSession.getSubjects(), session.getName(),
+                    session.getEventBridgeParameters());
+        } catch (Exception ex) {
+            throw new CayenneRuntimeException("Error creating EventBridge.", ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fadd1d1e/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java
new file mode 100644
index 0000000..ed4036c
--- /dev/null
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/HttpClientConnectionProvider.java
@@ -0,0 +1,75 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.rop;
+
+import org.apache.cayenne.ConfigurationException;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.RuntimeProperties;
+import org.apache.cayenne.di.DIRuntimeException;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.remote.ClientConnection;
+import org.apache.cayenne.rop.http.HttpROPConnector;
+
+public class HttpClientConnectionProvider implements Provider<ClientConnection> {
+
+    @Inject
+    protected RuntimeProperties runtimeProperties;
+    
+    @Inject
+    protected ROPSerializationService serializationService;
+
+    @Override
+    public ClientConnection get() throws DIRuntimeException {
+        String sharedSession = runtimeProperties
+                .get(Constants.ROP_SERVICE_SHARED_SESSION_PROPERTY);
+
+        HttpROPConnector ropConnector = createHttpRopConnector();
+        ProxyRemoteService remoteService = new ProxyRemoteService(serializationService, ropConnector);
+
+        HttpClientConnection clientConnection = new HttpClientConnection(remoteService, sharedSession);
+        ropConnector.setClientConnection(clientConnection);
+
+        return clientConnection;
+    }
+
+    protected HttpROPConnector createHttpRopConnector() {
+        String url = runtimeProperties.get(Constants.ROP_SERVICE_URL_PROPERTY);
+        if (url == null) {
+            throw new ConfigurationException(
+                    "No property defined for '%s', can't initialize HessianConnection",
+                    Constants.ROP_SERVICE_URL_PROPERTY);
+        }
+
+        String userName = runtimeProperties.get(Constants.ROP_SERVICE_USERNAME_PROPERTY);
+        String password = runtimeProperties.get(Constants.ROP_SERVICE_PASSWORD_PROPERTY);
+
+        long readTimeout = runtimeProperties.getLong(
+                Constants.ROP_SERVICE_TIMEOUT_PROPERTY,
+                -1L);
+
+        HttpROPConnector result = new HttpROPConnector(url, userName, password);
+
+        if (readTimeout > 0) {
+            result.setReadTimeout(readTimeout);
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fadd1d1e/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
index 198ab19..15a54ed 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/http/HttpROPConnector.java
@@ -19,7 +19,7 @@
 package org.apache.cayenne.rop.http;
 
 import org.apache.cayenne.remote.RemoteSession;
-import org.apache.cayenne.rop.DefaultClientConnection;
+import org.apache.cayenne.rop.HttpClientConnection;
 import org.apache.cayenne.rop.ROPConnector;
 import org.apache.cayenne.rop.ROPConstants;
 import org.apache.commons.logging.Log;
@@ -40,7 +40,7 @@ public class HttpROPConnector implements ROPConnector {
 
     public static final String SESSION_COOKIE_NAME = "JSESSIONID";
 
-    private DefaultClientConnection clientConnection;
+    private HttpClientConnection clientConnection;
 
     private String url;
 
@@ -55,7 +55,7 @@ public class HttpROPConnector implements ROPConnector {
         this.password = password;
     }
 
-    public void setClientConnection(DefaultClientConnection clientConnection) {
+    public void setClientConnection(HttpClientConnection clientConnection) {
         this.clientConnection = clientConnection;
     }
     

http://git-wip-us.apache.org/repos/asf/cayenne/blob/fadd1d1e/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java b/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
index 836507b..8786ff1 100644
--- a/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
+++ b/cayenne-client/src/test/java/org/apache/cayenne/configuration/rop/client/ClientModuleTest.java
@@ -28,7 +28,7 @@ import org.apache.cayenne.event.DefaultEventManager;
 import org.apache.cayenne.remote.ClientChannel;
 import org.apache.cayenne.remote.ClientConnection;
 import org.apache.cayenne.remote.MockClientConnection;
-import org.apache.cayenne.rop.DefaultClientConnection;
+import org.apache.cayenne.rop.HttpClientConnection;
 import org.junit.Test;
 
 import java.util.HashMap;
@@ -52,7 +52,7 @@ public class ClientModuleTest {
 
         ClientConnection connection = injector.getInstance(ClientConnection.class);
         assertNotNull(connection);
-        assertTrue(connection instanceof DefaultClientConnection);
+        assertTrue(connection instanceof HttpClientConnection);
 
         assertSame("Connection must be a singleton", connection, injector
                 .getInstance(ClientConnection.class));


[8/9] cayenne git commit: Mention that ROP server should now use new ROPServlet servlet class in the upgrade notes

Posted by dk...@apache.org.
Mention that ROP server should now use new ROPServlet servlet class in the upgrade notes


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/2c3719c0
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/2c3719c0
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/2c3719c0

Branch: refs/heads/master
Commit: 2c3719c0d52f400a27c54cd1db855b0a8273e013
Parents: 0e13274
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Tue Mar 1 17:21:04 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 17:21:04 2016 +0300

----------------------------------------------------------------------
 docs/doc/src/main/resources/UPGRADE.txt | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/2c3719c0/docs/doc/src/main/resources/UPGRADE.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/UPGRADE.txt b/docs/doc/src/main/resources/UPGRADE.txt
index 6887e19..fb5408d 100644
--- a/docs/doc/src/main/resources/UPGRADE.txt
+++ b/docs/doc/src/main/resources/UPGRADE.txt
@@ -9,6 +9,10 @@ UPGRADING TO 4.0.M4
 * 4.0.M4 changes the way queries are stored in the mapping files, so all existing *.map.xml files should be upgraded.
   To do that open each of your existing projects in the new CayenneModeler. Agree to perform an upgrade when asked.
 
+* Per CAY-2065 ROPHessianServlet has been discarded in favor of new implementation called ROPServlet,
+  so if you were using org.apache.cayenne.configuration.rop.server.ROPHessianServlet in your web.xml configuration,
+  you must change it to org.apache.cayenne.rop.ROPServlet
+
 UPGRADING TO 4.0.M3
 
 * Per CAY-2026 minimal Java version is now 1.7. If you are still need Java 1.6, you can use Cayenne 3.1 or 4.0.M2 until your


[7/9] cayenne git commit: Tests for hessian serialization service.

Posted by dk...@apache.org.
Tests for hessian serialization service.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/d96ddec1
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/d96ddec1
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/d96ddec1

Branch: refs/heads/master
Commit: d96ddec1c6860f93e4a1950f4554cdb2d05cd837
Parents: 1d9c26b
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Mon Jan 25 18:28:41 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 14:10:20 2016 +0300

----------------------------------------------------------------------
 .../http/HessianROPSerializationServiceIT.java  | 94 ++++++++++++++++++++
 1 file changed, 94 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/d96ddec1/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java b/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java
new file mode 100644
index 0000000..770b625
--- /dev/null
+++ b/cayenne-client/src/test/java/org/apache/cayenne/rop/http/HessianROPSerializationServiceIT.java
@@ -0,0 +1,94 @@
+package org.apache.cayenne.rop.http;
+
+import org.apache.cayenne.CayenneContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.rop.ROPSerializationService;
+import org.apache.cayenne.rop.ServerHessianSerializationServiceProvider;
+import org.apache.cayenne.testdo.mt.ClientMtTable1;
+import org.apache.cayenne.testdo.mt.ClientMtTable2;
+import org.apache.cayenne.unit.di.client.ClientCase;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import static org.junit.Assert.*;
+
+@UseServerRuntime(CayenneProjects.MULTI_TIER_PROJECT)
+public class HessianROPSerializationServiceIT extends ClientCase {
+	
+	@Inject
+	private CayenneContext context;
+
+	@Test
+	public void testByteArraySerialization() throws Exception {
+		ClientMtTable1 table1 = context.newObject(ClientMtTable1.class);
+		table1.setGlobalAttribute1("Test table1");
+
+		ClientMtTable2 table2 = context.newObject(ClientMtTable2.class);
+		table2.setGlobalAttribute("Test table2");
+		table2.setTable1(table1);
+
+		ROPSerializationService clientService = createClientSerializationService();
+		ROPSerializationService serverService = createServerSerializationService();
+		
+		// test client to server serialization
+		byte[] data = clientService.serialize(table2);
+		ClientMtTable2 serverTable2 = serverService.deserialize(data, ClientMtTable2.class);
+		
+		assertEquals("Test table2", serverTable2.getGlobalAttribute());
+		assertEquals("Test table1", serverTable2.getTable1().getGlobalAttribute1());
+		
+		// test server to client serialization
+		data = serverService.serialize(table2);
+		ClientMtTable2 clientTable2 = clientService.deserialize(data, ClientMtTable2.class);
+		
+		assertEquals("Test table2", clientTable2.getGlobalAttribute());
+		assertEquals("Test table1", clientTable2.getTable1().getGlobalAttribute1());
+	}
+
+	@Test
+	public void testStreamSerialization() throws Exception {
+		ClientMtTable1 table1 = context.newObject(ClientMtTable1.class);
+		table1.setGlobalAttribute1("Test table1");
+
+		ClientMtTable2 table2 = context.newObject(ClientMtTable2.class);
+		table2.setGlobalAttribute("Test table2");
+		table2.setTable1(table1);
+
+		ROPSerializationService clientService = createClientSerializationService();
+		ROPSerializationService serverService = createServerSerializationService();
+
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		
+		// test client to server serialization
+		clientService.serialize(table2, out);
+		out.flush();
+		ClientMtTable2 serverTable2 = serverService.deserialize(
+				new ByteArrayInputStream(out.toByteArray()), ClientMtTable2.class);
+
+		assertEquals("Test table2", serverTable2.getGlobalAttribute());
+		assertEquals("Test table1", serverTable2.getTable1().getGlobalAttribute1());
+
+		// test server to client serialization
+		out = new ByteArrayOutputStream();
+		serverService.serialize(table2, out);
+		out.flush();
+		ClientMtTable2 clientTable2 = clientService.deserialize(
+				new ByteArrayInputStream(out.toByteArray()), ClientMtTable2.class);
+
+		assertEquals("Test table2", clientTable2.getGlobalAttribute());
+		assertEquals("Test table1", clientTable2.getTable1().getGlobalAttribute1());
+	}
+
+	private ROPSerializationService createClientSerializationService() {
+		return new ClientHessianSerializationServiceProvider().get();
+	}
+
+	private ROPSerializationService createServerSerializationService() {
+		return new ServerHessianSerializationServiceProvider().get();
+	}
+	
+}


[6/9] cayenne git commit: Clean up old Hessian servlet implementation.

Posted by dk...@apache.org.
Clean up old Hessian servlet implementation.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/1d9c26b1
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/1d9c26b1
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/1d9c26b1

Branch: refs/heads/master
Commit: 1d9c26b1204adc8179ee4586979ab9772e4631ec
Parents: fadd1d1
Author: Dzmitry Kazimirchyk <dk...@gmail.com>
Authored: Mon Jan 25 18:27:02 2016 +0300
Committer: Dzmitry Kazimirchyk <dk...@gmail.com>
Committed: Tue Mar 1 14:10:20 2016 +0300

----------------------------------------------------------------------
 .../remote/hessian/HessianConnection.java       | 308 -------------------
 .../hessian/HessianURLConnectionFactory.java    |  51 ---
 .../remote/hessian/service/HessianUtil.java     |  11 +-
 .../org/apache/cayenne/rop/ROPConnector.java    |  15 +
 .../remote/hessian/HessianConnectionTest.java   |  81 -----
 .../rop/server/ROPHessianServlet.java           | 127 --------
 .../cayenne/configuration/web/WebUtil.java      |   3 +-
 .../rop/server/ROPHessianServletTest.java       | 183 -----------
 .../rop/server/ROPServletTest.java              | 179 +++++++++++
 9 files changed, 201 insertions(+), 757 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
deleted file mode 100644
index 372cfc7..0000000
--- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianConnection.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.remote.hessian;
-
-import com.caucho.hessian.client.HessianProxyFactory;
-import com.caucho.hessian.client.HessianRuntimeException;
-import com.caucho.hessian.io.HessianProtocolException;
-import com.caucho.hessian.io.SerializerFactory;
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.event.EventBridge;
-import org.apache.cayenne.event.EventBridgeFactory;
-import org.apache.cayenne.remote.BaseConnection;
-import org.apache.cayenne.remote.ClientMessage;
-import org.apache.cayenne.remote.RemoteService;
-import org.apache.cayenne.remote.RemoteSession;
-import org.apache.cayenne.util.Util;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * An ClientConnection that passes messages to a remotely deployed HessianService. It
- * supports HTTP BASIC authentication. HessianConnection serializes messages using Hessian
- * binary web service protocol over HTTP. For more info on Hessian see Caucho site at <a
- * href="http://www.caucho.com/resin-3.0/protocols/hessian.xtp">http://www.caucho.com/resin-3.0/protocols/hessian.xtp</a>.
- * HessianConnection supports logging of message traffic via Jakarta commons-logging API.
- *
- * @since 1.2
- */
-public class HessianConnection extends BaseConnection {
-
-    private static Log logger = LogFactory.getLog(HessianConnection.class);
-
-    public static final String[] CLIENT_SERIALIZER_FACTORIES = new String[] {
-            ClientSerializerFactory.class.getName()
-    };
-
-    protected String url;
-    protected String userName;
-    protected String password;
-    protected String sharedSessionName;
-
-    protected RemoteSession session;
-    protected RemoteService service;
-    protected SerializerFactory serializerFactory;
-
-    /**
-     * Creates HessianConnection that will establish dedicated session and will not use
-     * HTTP basic authentication.
-     */
-    public HessianConnection(String url) {
-        this(url, null, null, null);
-    }
-
-    /**
-     * Creates a HessianConnection. This constructor can optionally setup basic
-     * authentication credentials and configure shared session. <code>url</code> is the
-     * only required parameter.
-     */
-    public HessianConnection(String url, String userName, String password,
-            String sharedSessionName) {
-        if (url == null) {
-            throw new IllegalArgumentException("URL of Cayenne service is null.");
-        }
-
-        this.url = url;
-        this.userName = userName;
-        this.password = password;
-        this.sharedSessionName = sharedSessionName;
-    }
-
-    /**
-     * Returns a URL of Cayenne service used by this connector.
-     */
-    public String getUrl() {
-        return url;
-    }
-
-    /**
-     * Returns user name that is used for basic authentication when connecting to the
-     * cayenne server.
-     */
-    public String getUserName() {
-        return userName;
-    }
-
-    /**
-     * Returns password that is used for basic authentication when connecting to the
-     * cayenne server.
-     */
-    public String getPassword() {
-        return password;
-    }
-
-    public String getSharedSessionName() {
-        return sharedSessionName;
-    }
-
-    @Override
-    public EventBridge getServerEventBridge() throws CayenneRuntimeException {
-        if (session == null) {
-            connect();
-        }
-
-        return createServerEventBridge(session);
-    }
-
-    /**
-     * Creates an EventBridge that will listen for server events. Returns null if server
-     * events support is not configured in the descriptor.
-     *
-     * @throws CayenneRuntimeException if EventBridge startup fails for any reason.
-     */
-    protected EventBridge createServerEventBridge(RemoteSession session) throws CayenneRuntimeException {
-
-        if (!session.isServerEventsEnabled()) {
-            return null;
-        }
-
-        try {
-            EventBridgeFactory factory = (EventBridgeFactory) Class.forName(session.getEventBridgeFactory())
-                    .newInstance();
-
-            // must use "name", not the sessionId as an external subject for the
-            // event bridge
-            return factory.createEventBridge(RemoteSession.getSubjects(), session.getName(),
-                    session.getEventBridgeParameters());
-        } catch (Exception ex) {
-            throw new CayenneRuntimeException("Error creating EventBridge.", ex);
-        }
-    }
-
-    /**
-     * Returns internal RemoteSession instance.
-     */
-    public RemoteSession getSession() {
-        return session;
-    }
-
-    /**
-     * Establishes server session if needed.
-     */
-    @Override
-    protected void beforeSendMessage(ClientMessage message)
-            throws CayenneRuntimeException {
-        // for now only support session-based communications...
-        if (session == null) {
-            connect();
-        }
-    }
-
-    /**
-     * Sends a message to remote Cayenne Hessian service.
-     */
-    @Override
-    protected Object doSendMessage(ClientMessage message) throws CayenneRuntimeException {
-        try {
-            return service.processMessage(message);
-        }
-        catch (CayenneRuntimeException e) {
-            throw e;
-        }
-        catch (Throwable th) {
-            th = unwindThrowable(th);
-            String errorMessage = buildExceptionMessage("Remote error", th);
-            throw new CayenneRuntimeException(errorMessage, th);
-        }
-    }
-
-    /**
-     * Establishes a session with remote service.
-     */
-    protected synchronized void connect() throws CayenneRuntimeException {
-        if (session != null) {
-            return;
-        }
-
-        long t0 = 0;
-        if (logger.isInfoEnabled()) {
-            t0 = System.currentTimeMillis();
-            StringBuilder log = new StringBuilder("Connecting to [");
-            if (userName != null) {
-                log.append(userName);
-
-                if (password != null) {
-                    log.append(":*******");
-                }
-
-                log.append("@");
-            }
-
-            log.append(url);
-            log.append("]");
-
-            if (sharedSessionName != null) {
-                log.append(" - shared session '").append(sharedSessionName).append("'");
-            }
-            else {
-                log.append(" - dedicated session.");
-            }
-
-            logger.info(log.toString());
-        }
-
-        // init service proxy...
-        HessianProxyFactory factory = new HessianProxyFactory();
-        factory.setSerializerFactory(HessianConfig.createFactory(
-                CLIENT_SERIALIZER_FACTORIES,
-                null));
-        factory.setConnectionFactory(new HessianURLConnectionFactory(this));
-        factory.setUser(userName);
-        factory.setPassword(password);
-
-        this.serializerFactory = factory.getSerializerFactory();
-
-        try {
-            this.service = (RemoteService) factory.create(RemoteService.class, url);
-        }
-        catch (Throwable th) {
-            th = unwindThrowable(th);
-            String message = buildExceptionMessage("URL error", th);
-            throw new CayenneRuntimeException(message, th);
-        }
-
-        // create server session...
-        try {
-            session = (sharedSessionName != null) ? service
-                    .establishSharedSession(sharedSessionName) : service
-                    .establishSession();
-
-            if (logger.isInfoEnabled()) {
-                long time = System.currentTimeMillis() - t0;
-                logger.info("=== Connected, session: "
-                        + session
-                        + " - took "
-                        + time
-                        + " ms.");
-            }
-        }
-        catch (Throwable th) {
-            th = unwindThrowable(th);
-            String message = buildExceptionMessage(
-                    "Error establishing remote session",
-                    th);
-            logger.info(message, th);
-            throw new CayenneRuntimeException(message, th);
-        }
-
-        // TODO: send a connect event...
-    }
-
-    String buildExceptionMessage(String message, Throwable th) {
-
-        StringBuilder buffer = new StringBuilder(message);
-        buffer.append(". URL - ").append(url);
-
-        String thMessage = th.getMessage();
-        if (!Util.isEmptyString(thMessage)) {
-            buffer.append("; CAUSE - ").append(thMessage);
-        }
-
-        return buffer.toString();
-    }
-
-    /**
-     * Utility method to get exception cause. Implements special handling of Hessian
-     * exceptions.
-     */
-    Throwable unwindThrowable(Throwable th) {
-        if (th instanceof HessianProtocolException) {
-            Throwable cause = ((HessianProtocolException) th).getRootCause();
-
-            if (cause != null) {
-                return unwindThrowable(cause);
-            }
-        }
-        else if (th instanceof HessianRuntimeException) {
-            Throwable cause = ((HessianRuntimeException) th).getRootCause();
-
-            if (cause != null) {
-                return unwindThrowable(cause);
-            }
-        }
-
-        return Util.unwindException(th);
-    }
-
-    public SerializerFactory getSerializerFactory() {
-        return serializerFactory;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianURLConnectionFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianURLConnectionFactory.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianURLConnectionFactory.java
deleted file mode 100644
index d5a441f..0000000
--- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/HessianURLConnectionFactory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.remote.hessian;
-
-import org.apache.cayenne.remote.RemoteSession;
-
-import java.io.IOException;
-import java.net.URL;
-
-public class HessianURLConnectionFactory extends com.caucho.hessian.client.HessianURLConnectionFactory {
-
-    static final String SESSION_COOKIE_NAME = "JSESSIONID";
-
-    private HessianConnection clientConnection;
-
-    HessianURLConnectionFactory(HessianConnection clientConnection) {
-        this.clientConnection = clientConnection;
-    }
-
-    @Override
-    public com.caucho.hessian.client.HessianConnection open(URL url) throws IOException {
-        com.caucho.hessian.client.HessianConnection hessianConnection = super.open(url);
-
-        // add session cookie
-        RemoteSession session = clientConnection.getSession();
-        if (session != null && session.getSessionId() != null) {
-            hessianConnection.addHeader("Cookie", SESSION_COOKIE_NAME
-                    + "="
-                    + session.getSessionId());
-        }
-
-        return hessianConnection;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/service/HessianUtil.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/service/HessianUtil.java b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/service/HessianUtil.java
index 7c0f15c..88a938b 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/service/HessianUtil.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/remote/hessian/service/HessianUtil.java
@@ -25,10 +25,11 @@ import java.io.Serializable;
 
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.remote.hessian.HessianConfig;
-import org.apache.cayenne.remote.hessian.HessianConnection;
 
 import com.caucho.hessian.io.HessianInput;
 import com.caucho.hessian.io.HessianOutput;
+import org.apache.cayenne.rop.ServerHessianSerializationServiceProvider;
+import org.apache.cayenne.rop.http.ClientHessianSerializationServiceProvider;
 
 /**
  * Hessian related utilities.
@@ -47,7 +48,7 @@ public class HessianUtil {
         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
         HessianOutput out = new HessianOutput(bytes);
         out.setSerializerFactory(HessianConfig.createFactory(
-                HessianConnection.CLIENT_SERIALIZER_FACTORIES,
+                ClientHessianSerializationServiceProvider.CLIENT_SERIALIZER_FACTORIES,
                 null));
         out.writeObject(object);
 
@@ -55,7 +56,7 @@ public class HessianUtil {
 
         HessianInput in = new HessianInput(new ByteArrayInputStream(data));
         in.setSerializerFactory(HessianConfig.createFactory(
-                HessianService.SERVER_SERIALIZER_FACTORIES,
+                ServerHessianSerializationServiceProvider.SERVER_SERIALIZER_FACTORIES,
                 serverResolver));
 
         return in.readObject();
@@ -67,7 +68,7 @@ public class HessianUtil {
         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
         HessianOutput out = new HessianOutput(bytes);
         out.setSerializerFactory(HessianConfig.createFactory(
-                HessianService.SERVER_SERIALIZER_FACTORIES,
+				ServerHessianSerializationServiceProvider.SERVER_SERIALIZER_FACTORIES,
                 serverResolver));
         out.writeObject(object);
 
@@ -75,7 +76,7 @@ public class HessianUtil {
 
         HessianInput in = new HessianInput(new ByteArrayInputStream(data));
         in.setSerializerFactory(HessianConfig.createFactory(
-                HessianConnection.CLIENT_SERIALIZER_FACTORIES,
+                ClientHessianSerializationServiceProvider.CLIENT_SERIALIZER_FACTORIES,
                 null));
         return in.readObject();
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java b/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java
index 4976d80..5855cf8 100644
--- a/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java
+++ b/cayenne-client/src/main/java/org/apache/cayenne/rop/ROPConnector.java
@@ -21,12 +21,27 @@ package org.apache.cayenne.rop;
 import java.io.IOException;
 import java.io.InputStream;
 
+/**
+ * ROP network connectivity interface.
+ * 
+ * @since 4.0
+ */
 public interface ROPConnector {
 
+	/**
+	 * Establishes a dedicated session with Cayenne DataChannel, returning session id.
+	 */
     InputStream establishSession() throws IOException;
 
+	/**
+	 * Creates a new session with the specified or joins an existing one. This method is
+	 * used to bootstrap collaborating clients of a single "group chat".
+	 */
     InputStream establishSharedSession(String name) throws IOException;
 
+	/**
+	 * Processes message on a remote server, returning the result of such processing.
+	 */
     InputStream sendMessage(byte[] message) throws IOException;
     
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-client/src/test/java/org/apache/cayenne/remote/hessian/HessianConnectionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-client/src/test/java/org/apache/cayenne/remote/hessian/HessianConnectionTest.java b/cayenne-client/src/test/java/org/apache/cayenne/remote/hessian/HessianConnectionTest.java
deleted file mode 100644
index e3808ed..0000000
--- a/cayenne-client/src/test/java/org/apache/cayenne/remote/hessian/HessianConnectionTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-
-package org.apache.cayenne.remote.hessian;
-
-import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.remote.ClientMessage;
-import org.apache.cayenne.remote.RemoteService;
-import org.apache.cayenne.remote.RemoteSession;
-import org.apache.cayenne.remote.service.MissingSessionException;
-import org.junit.Test;
-
-import java.rmi.RemoteException;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-public class HessianConnectionTest {
-
-    @Test
-    public void testConstructor1Arg() {
-        HessianConnection c = new HessianConnection("a");
-        assertEquals("a", c.getUrl());
-        assertNull(c.getUserName());
-        assertNull(c.getPassword());
-    }
-
-    @Test
-    public void testConstructor3Arg() {
-        HessianConnection c = new HessianConnection("a", "b", "c", "d");
-        assertEquals("a", c.getUrl());
-        assertEquals("b", c.getUserName());
-        assertEquals("c", c.getPassword());
-        assertEquals("d", c.getSharedSessionName());
-    }
-
-    @Test
-    public void testMissingSessionException() {
-        // Set up the test objects.  We want to mock out RemoteService.
-        HessianConnection c = new HessianConnection("a");
-        c.service = new RemoteService() {
-            public RemoteSession establishSession() throws RemoteException {
-                return null;
-            }
-
-            public RemoteSession establishSharedSession(String name) throws RemoteException {
-                return null;
-            }
-
-            public Object processMessage(ClientMessage message) throws RemoteException, Throwable {
-                throw new MissingSessionException();
-            }
-        };
-
-
-        try {
-            c.doSendMessage(null);
-        }
-        catch (CayenneRuntimeException e) {
-            // Verify that CayenneRuntimeExceptions are not wrapped in another CayenneRuntimeException.
-            assertTrue(e instanceof MissingSessionException);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPHessianServlet.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPHessianServlet.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPHessianServlet.java
deleted file mode 100644
index 3059a5b..0000000
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/rop/server/ROPHessianServlet.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.configuration.rop.server;
-
-import java.util.Collection;
-import java.util.Map;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-
-import org.apache.cayenne.DataChannel;
-import org.apache.cayenne.configuration.CayenneRuntime;
-import org.apache.cayenne.configuration.server.ServerRuntime;
-import org.apache.cayenne.configuration.web.RequestHandler;
-import org.apache.cayenne.configuration.web.WebConfiguration;
-import org.apache.cayenne.configuration.web.WebUtil;
-import org.apache.cayenne.di.Module;
-import org.apache.cayenne.event.EventBridge;
-import org.apache.cayenne.remote.RemoteService;
-import org.apache.cayenne.remote.hessian.HessianConfig;
-import org.apache.cayenne.remote.hessian.service.HessianService;
-
-import com.caucho.hessian.io.SerializerFactory;
-import com.caucho.hessian.server.HessianServlet;
-
-/**
- * A servlet that bootstraps a Hessian-based ROP server. Servlet initialization
- * parameters:
- * <ul>
- * <li>configuration-location (optional) - a name of Cayenne configuration XML file that
- * will be used to load Cayenne stack. If missing, the servlet name will be used to derive
- * the location. ".xml" extension will be appended to the servlet name to get the
- * location, so a servlet named "cayenne-foo" will result in location "cayenne-foo.xml".
- * <li>extra-modules (optional) - a comma or space-separated list of class names, with
- * each class implementing {@link Module} interface. These are the custom modules loaded
- * after the two standard ones that allow users to override any Cayenne runtime aspects,
- * e.g. {@link RequestHandler}. Each custom module must have a no-arg constructor.
- * </ul>
- * All other parameters passed to the servlet are considered to be related to the
- * {@link EventBridge} initialization.
- * 
- * @since 3.1
- */
-public class ROPHessianServlet extends HessianServlet {
-
-    protected ServletContext servletContext;
-
-    /**
-     * Installs {@link HessianService} to respond to {@link RemoteService} requests.
-     */
-    @Override
-    public void init(ServletConfig configuration) throws ServletException {
-        
-        checkAlreadyConfigured(configuration.getServletContext());
-
-        this.servletContext = configuration.getServletContext();
-
-        WebConfiguration configAdapter = new WebConfiguration(configuration);
-
-        String configurationLocation = configAdapter.getConfigurationLocation();
-        Map<String, String> eventBridgeParameters = configAdapter.getOtherParameters();
-
-        Collection<Module> modules = configAdapter.createModules(new ROPServerModule(
-                eventBridgeParameters));
-
-        ServerRuntime runtime = new ServerRuntime(configurationLocation, modules
-                .toArray(new Module[modules.size()]));
-
-        DataChannel channel = runtime.getChannel();
-
-        RemoteService service = runtime.getInjector().getInstance(RemoteService.class);
-
-        SerializerFactory serializerFactory = HessianConfig.createFactory(
-                HessianService.SERVER_SERIALIZER_FACTORIES,
-                channel.getEntityResolver());
-
-        setAPIClass(RemoteService.class);
-        setSerializerFactory(serializerFactory);
-        setService(service);
-
-        // Even though runtime instance is not accessed by Hessian service directly (it
-        // uses DataChannel injection instead), expose it in a manner consistent with
-        // CayenneFilter. Servlets other than ROP may decide to use it...
-
-        // TODO: andrus 04/14/2010: if CayenneFilter and ROPHessianServlet are used
-        // together in the same webapp, maybe a good idea to ensure they are using the
-        // same stack...Merging CayenneRuntime's modules might be tough though.
-
-        WebUtil.setCayenneRuntime(servletContext, runtime);
-        super.init(configuration);
-    }
-    
-    protected void checkAlreadyConfigured(ServletContext context) throws ServletException {
-        // sanity check
-        if (WebUtil.getCayenneRuntime(context) != null) {
-            throw new ServletException(
-                    "CayenneRuntime is already configured in the servlet environment");
-        }
-    }
-
-    @Override
-    public void destroy() {
-        super.destroy();
-
-        CayenneRuntime runtime = WebUtil.getCayenneRuntime(servletContext);
-        if (runtime != null) {
-            runtime.shutdown();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-server/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java b/cayenne-server/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java
index 244d5c3..dfeb3c4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java
@@ -21,12 +21,11 @@ package org.apache.cayenne.configuration.web;
 import javax.servlet.ServletContext;
 
 import org.apache.cayenne.configuration.CayenneRuntime;
-import org.apache.cayenne.configuration.rop.server.ROPHessianServlet;
 
 /**
  * A helper class to retrieve and store {@link CayenneRuntime} in the
  * {@link ServletContext}. All Cayenne web configuration objects, such as
- * {@link CayenneFilter} and {@link ROPHessianServlet}, are using this class to access
+ * {@link CayenneFilter} and {@link org.apache.cayenne.rop.ROPServlet}, are using this class to access
  * runtime.
  * 
  * @since 3.1

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPHessianServletTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPHessianServletTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPHessianServletTest.java
deleted file mode 100644
index cf4bc52..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPHessianServletTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne.configuration.rop.server;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.cayenne.configuration.CayenneRuntime;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.ModuleCollection;
-import org.apache.cayenne.configuration.server.ServerModule;
-import org.apache.cayenne.configuration.web.MockModule1;
-import org.apache.cayenne.configuration.web.MockModule2;
-import org.apache.cayenne.configuration.web.MockRequestHandler;
-import org.apache.cayenne.configuration.web.RequestHandler;
-import org.apache.cayenne.configuration.web.WebUtil;
-import org.apache.cayenne.di.Key;
-import org.apache.cayenne.di.Module;
-import org.apache.cayenne.remote.RemoteService;
-import org.junit.Test;
-
-import com.mockrunner.mock.web.MockServletConfig;
-import com.mockrunner.mock.web.MockServletContext;
-
-public class ROPHessianServletTest {
-
-	@Test
-	public void testInitWithServletName() throws Exception {
-
-		MockServletConfig config = new MockServletConfig();
-		config.setServletName("cayenne-org.apache.cayenne.configuration.rop.server.test-config");
-
-		MockServletContext context = new MockServletContext();
-		config.setServletContext(context);
-
-		ROPHessianServlet servlet = new ROPHessianServlet();
-
-		assertNull(WebUtil.getCayenneRuntime(context));
-		servlet.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-
-		List<?> locations = runtime.getInjector().getInstance(
-				Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
-		assertEquals(Arrays.asList("cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml"), locations);
-	}
-
-	@Test
-	public void testInitWithLocation() throws Exception {
-
-		String location = "cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml";
-		MockServletConfig config = new MockServletConfig();
-		config.setServletName("abc");
-		config.setInitParameter("configuration-location", location);
-
-		MockServletContext context = new MockServletContext();
-		config.setServletContext(context);
-
-		ROPHessianServlet servlet = new ROPHessianServlet();
-		servlet.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-		List<?> locations = runtime.getInjector().getInstance(
-				Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
-
-		assertEquals(Arrays.asList(location), locations);
-	}
-
-	@Test
-	public void testInitWithStandardModules() throws Exception {
-
-		String name = "cayenne-org.apache.cayenne.configuration.rop.server.test-config";
-
-		MockServletConfig config = new MockServletConfig();
-		config.setServletName(name);
-
-		MockServletContext context = new MockServletContext();
-		config.setServletContext(context);
-
-		ROPHessianServlet servlet = new ROPHessianServlet();
-		servlet.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-
-		List<?> locations = runtime.getInjector().getInstance(
-				Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
-
-		assertEquals(Arrays.asList(name + ".xml"), locations);
-		
-		Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
-		assertEquals(2, modules.size());
-		Object[] marray = modules.toArray();
-
-		assertTrue(marray[0] instanceof ServerModule);
-		assertTrue(marray[1] instanceof ROPServerModule);
-
-		assertTrue(RemoteService.class.equals(servlet.getAPIClass()));
-	}
-
-	@Test
-	public void testInitWithExtraModules() throws Exception {
-
-		String name = "cayenne-org.apache.cayenne.configuration.rop.server.test-config";
-
-		MockServletConfig config = new MockServletConfig();
-		config.setServletName(name);
-		config.setInitParameter("extra-modules", MockModule1.class.getName() + "," + MockModule2.class.getName());
-
-		MockServletContext context = new MockServletContext();
-		config.setServletContext(context);
-
-		ROPHessianServlet servlet = new ROPHessianServlet();
-		servlet.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-
-		Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
-		assertEquals(4, modules.size());
-
-		Object[] marray = modules.toArray();
-
-		assertTrue(marray[0] instanceof ServerModule);
-		assertTrue(marray[1] instanceof ROPServerModule);
-		assertTrue(marray[2] instanceof MockModule1);
-		assertTrue(marray[3] instanceof MockModule2);
-
-		RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
-		assertTrue(handler instanceof MockRequestHandler);
-	}
-
-	@Test
-	public void testInitHessianService() throws Exception {
-
-		MockServletConfig config = new MockServletConfig();
-		config.setServletName("abc");
-
-		MockServletContext context = new MockServletContext();
-		config.setServletContext(context);
-		config.setInitParameter("extra-modules", ROPHessianServlet_ConfigModule.class.getName());
-
-		ROPHessianServlet servlet = new ROPHessianServlet();
-
-		servlet.init(config);
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
-		assertEquals(3, modules.size());
-
-		Object[] marray = modules.toArray();
-
-		assertTrue(marray[2] instanceof ROPHessianServlet_ConfigModule);
-
-		assertTrue(RemoteService.class.equals(servlet.getAPIClass()));
-
-		// TODO: mock servlet request to check that the right service instance
-		// is invoked
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/1d9c26b1/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPServletTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPServletTest.java b/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPServletTest.java
new file mode 100644
index 0000000..569d703
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/configuration/rop/server/ROPServletTest.java
@@ -0,0 +1,179 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.configuration.rop.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.cayenne.configuration.CayenneRuntime;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.ModuleCollection;
+import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.configuration.web.MockModule1;
+import org.apache.cayenne.configuration.web.MockModule2;
+import org.apache.cayenne.configuration.web.MockRequestHandler;
+import org.apache.cayenne.configuration.web.RequestHandler;
+import org.apache.cayenne.configuration.web.WebUtil;
+import org.apache.cayenne.di.Key;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.rop.ROPServlet;
+import org.junit.Test;
+
+import com.mockrunner.mock.web.MockServletConfig;
+import com.mockrunner.mock.web.MockServletContext;
+
+public class ROPServletTest {
+
+	@Test
+	public void testInitWithServletName() throws Exception {
+
+		MockServletConfig config = new MockServletConfig();
+		config.setServletName("cayenne-org.apache.cayenne.configuration.rop.server.test-config");
+
+		MockServletContext context = new MockServletContext();
+		config.setServletContext(context);
+
+		ROPServlet servlet = new ROPServlet();
+
+		assertNull(WebUtil.getCayenneRuntime(context));
+		servlet.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+
+		List<?> locations = runtime.getInjector().getInstance(
+				Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
+		assertEquals(Arrays.asList("cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml"), locations);
+	}
+
+	@Test
+	public void testInitWithLocation() throws Exception {
+
+		String location = "cayenne-org.apache.cayenne.configuration.rop.server.test-config.xml";
+		MockServletConfig config = new MockServletConfig();
+		config.setServletName("abc");
+		config.setInitParameter("configuration-location", location);
+
+		MockServletContext context = new MockServletContext();
+		config.setServletContext(context);
+
+		ROPServlet servlet = new ROPServlet();
+		servlet.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+		List<?> locations = runtime.getInjector().getInstance(
+				Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
+
+		assertEquals(Arrays.asList(location), locations);
+	}
+
+	@Test
+	public void testInitWithStandardModules() throws Exception {
+
+		String name = "cayenne-org.apache.cayenne.configuration.rop.server.test-config";
+
+		MockServletConfig config = new MockServletConfig();
+		config.setServletName(name);
+
+		MockServletContext context = new MockServletContext();
+		config.setServletContext(context);
+
+		ROPServlet servlet = new ROPServlet();
+		servlet.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+
+		List<?> locations = runtime.getInjector().getInstance(
+				Key.get(List.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
+
+		assertEquals(Arrays.asList(name + ".xml"), locations);
+		
+		Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
+		assertEquals(2, modules.size());
+		Object[] marray = modules.toArray();
+
+		assertTrue(marray[0] instanceof ServerModule);
+		assertTrue(marray[1] instanceof ROPServerModule);
+	}
+
+	@Test
+	public void testInitWithExtraModules() throws Exception {
+
+		String name = "cayenne-org.apache.cayenne.configuration.rop.server.test-config";
+
+		MockServletConfig config = new MockServletConfig();
+		config.setServletName(name);
+		config.setInitParameter("extra-modules", MockModule1.class.getName() + "," + MockModule2.class.getName());
+
+		MockServletContext context = new MockServletContext();
+		config.setServletContext(context);
+
+		ROPServlet servlet = new ROPServlet();
+		servlet.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+
+		Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
+		assertEquals(4, modules.size());
+
+		Object[] marray = modules.toArray();
+
+		assertTrue(marray[0] instanceof ServerModule);
+		assertTrue(marray[1] instanceof ROPServerModule);
+		assertTrue(marray[2] instanceof MockModule1);
+		assertTrue(marray[3] instanceof MockModule2);
+
+		RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
+		assertTrue(handler instanceof MockRequestHandler);
+	}
+
+	@Test
+	public void testInitHessianService() throws Exception {
+
+		MockServletConfig config = new MockServletConfig();
+		config.setServletName("abc");
+
+		MockServletContext context = new MockServletContext();
+		config.setServletContext(context);
+		config.setInitParameter("extra-modules", ROPHessianServlet_ConfigModule.class.getName());
+
+		ROPServlet servlet = new ROPServlet();
+
+		servlet.init(config);
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		Collection<Module> modules = ((ModuleCollection) runtime.getModule()).getModules();
+		assertEquals(3, modules.size());
+
+		Object[] marray = modules.toArray();
+
+		assertTrue(marray[2] instanceof ROPHessianServlet_ConfigModule);
+
+		// TODO: mock servlet request to check that the right service instance
+		// is invoked
+	}
+}