diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/FacadeFactory.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/FacadeFactory.java
index 12b08542ac0f6dc46435afc146119855597e3a16..0f119a3f0cdf1fa9df6db19ffddb890f7d3058e6 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/FacadeFactory.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/FacadeFactory.java
@@ -17,30 +17,35 @@
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.client.api.v1;
 
 import ch.systemsx.cisd.common.api.client.ServiceFinder;
-import ch.systemsx.cisd.openbis.plugin.phosphonetx.server.api.v1.Constants;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.IRawDataService;
 
 /**
  * Factory of {@link IRawDataApiFacade}.
- *
+ * 
  * @author Franz-Josef Elmer
  */
 public class FacadeFactory
 {
-    private static final ServiceFinder SERVICE_FINDER = new ServiceFinder("openbis", Constants.RAW_DATA_SERVER_URL);
+    private static final ServiceFinder SERVICE_FINDER =
+            new ServiceFinder("openbis", IRawDataService.SERVER_URL);
+
+    private static final ServiceFinder GENERIC_INFO_SERVICE_FINDER =
+            new ServiceFinder("openbis", IGeneralInformationService.SERVICE_URL);
 
     /**
      * Creates a facade for specified server URL, user Id, and password.
      */
     public static IRawDataApiFacade create(String serverURL, String userID, String password)
     {
+        IGeneralInformationService infoService = createGenericInfoService(serverURL);
         IRawDataService service = createService(serverURL);
-        String sessionToken = service.tryToAuthenticateAtRawDataServer(userID, password);
+        String sessionToken = infoService.tryToAuthenticateForAllServices(userID, password);
         if (sessionToken == null)
         {
             throw new IllegalArgumentException("User " + userID + " couldn't be authenticated");
         }
-        return new RawDataApiFacade(service, sessionToken);
+        return new RawDataApiFacade(service, infoService, sessionToken);
     }
 
     /**
@@ -48,12 +53,19 @@ public class FacadeFactory
      */
     public static IRawDataApiFacade create(String serverURL, String sessionToken)
     {
-        return new RawDataApiFacade(createService(serverURL), sessionToken);
+        IRawDataService service = createService(serverURL);
+        IGeneralInformationService infoService = createGenericInfoService(serverURL);
+        return new RawDataApiFacade(service, infoService, sessionToken);
     }
 
     private static IRawDataService createService(String serverURL)
     {
         return SERVICE_FINDER.createService(IRawDataService.class, serverURL);
     }
+
+    private static IGeneralInformationService createGenericInfoService(String serverURL)
+    {
+        return GENERIC_INFO_SERVICE_FINDER.createService(IGeneralInformationService.class, serverURL);
+    }
     
 }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/IRawDataApiFacade.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/IRawDataApiFacade.java
index 91f9a45ff8317c1c53f4c5d8da431366fec64860..b47e523e82afd437faf9259bff3f4e2b9e15cc89 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/IRawDataApiFacade.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/IRawDataApiFacade.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.plugin.phosphonetx.client.api.v1;
 
 import java.util.List;
 
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.DataStoreServerProcessingPluginInfo;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.MsInjectionDataInfo;
 
@@ -51,6 +52,11 @@ public interface IRawDataApiFacade
      */
     public void processingRawData(String userID, String dataSetProcessingKey,
             long[] rawDataSampleIDs, String dataSetType);
+    
+    /**
+     * Returns all projects where the specified user has USER access rights.
+     */
+    public List<Project> listProjects(String userID);
 
     /**
      * Logs current user out.
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiFacade.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiFacade.java
index 4ef94ccef81c294c87d02647cfb501c2525d425c..29b9631f2a24e29d5772e14df1c9788013632b0b 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiFacade.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiFacade.java
@@ -16,8 +16,15 @@
 
 package ch.systemsx.cisd.openbis.plugin.phosphonetx.client.api.v1;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Role;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.IRawDataService;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.DataStoreServerProcessingPluginInfo;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.MsInjectionDataInfo;
@@ -29,12 +36,15 @@ import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.MsInjection
  */
 class RawDataApiFacade implements IRawDataApiFacade
 {
+    private static final String USER_ROLE_SET = "USER";
     private final IRawDataService service;
+    private final IGeneralInformationService generalInfoService;
     private final String sessionToken;
 
-    RawDataApiFacade(IRawDataService service, String sessionToken)
+    RawDataApiFacade(IRawDataService service, IGeneralInformationService generalInfoService, String sessionToken)
     {
         this.service = service;
+        this.generalInfoService = generalInfoService;
         this.sessionToken = sessionToken;
     }
 
@@ -60,9 +70,37 @@ class RawDataApiFacade implements IRawDataApiFacade
                 dataSetType);
     }
 
+    public List<Project> listProjects(String userID)
+    {
+        Map<String, Set<Role>> namedRoleSets = generalInfoService.listNamedRoleSets(sessionToken);
+        Set<Role> allowedRoles = namedRoleSets.get(USER_ROLE_SET);
+        if (allowedRoles == null)
+        {
+            throw new IllegalStateException("Role set " + USER_ROLE_SET + " not known.");
+        }
+        
+        List<SpaceWithProjectsAndRoleAssignments> spaces =
+                generalInfoService.listSpacesWithProjectsAndRoleAssignments(sessionToken, null);
+        List<Project> projects = new ArrayList<Project>();
+        for (SpaceWithProjectsAndRoleAssignments space : spaces)
+        {
+            Set<Role> roles = space.getRoles(userID);
+            roles.retainAll(allowedRoles);
+            if (roles.isEmpty() == false)
+            {
+                for (ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project project : space
+                        .getProjects())
+                {
+                    projects.add(new Project(space.getCode(), project.getCode()));
+                }
+            }
+        }
+        return projects;
+    }
+
     public void logout()
     {
-        service.logout(sessionToken);
+        generalInfoService.logout(sessionToken);
     }
     
 }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiTest.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiTest.java
index 8ac8fadc944e0c34fce6840146ce80e3c7321e8e..81ccf122bcc5689bbc4f2bc5f883e30d58963446 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiTest.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiTest.java
@@ -20,6 +20,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.DataStoreServerProcessingPluginInfo;
 import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.MsInjectionDataInfo;
 
@@ -65,6 +66,13 @@ public class RawDataApiTest
             System.out.println("   key:" + info.getKey() + ", label:'" + info.getLabel()
                     + "', data set types:" + info.getDatasetTypeCodes());
         }
+        
+        System.out.println("Projects:");
+        List<Project> projects = facade.listProjects(userID);
+        for (Project project : projects)
+        {
+            System.out.println(project);
+        }
         facade.logout();
     }
 }
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/Constants.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/Constants.java
index afc228880b9ed429f14ee1de82855086abbad536..728de9189d9556bd6784d714f9c2998fe273719f 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/Constants.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/Constants.java
@@ -23,7 +23,7 @@ package ch.systemsx.cisd.openbis.plugin.phosphonetx.server.api.v1;
  */
 public class Constants
 {
-    public final static String RAW_DATA_SERVER_URL = "/rmi-phosphonetx-raw-data-v1";
+    // Spring bean IDs
     public final static String PHOSPHONETX_RAW_DATA_SERVICE = "phosphonetx-raw-data-service";
     public final static String PHOSPHONETX_RAW_DATA_SERVICE_INTERNAL = "phosphonetx-raw-data-service-internal";
 
diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/RawDataServiceServer.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/RawDataServiceServer.java
index d3a1eb303e91612fdb09e892278a70723874324d..5f4def48cff631bbbd34de7ae8af2a018f361133 100644
--- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/RawDataServiceServer.java
+++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/server/api/v1/RawDataServiceServer.java
@@ -35,7 +35,7 @@ import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.IRawDataService
  */
 @Controller
 @RequestMapping(
-    { Constants.RAW_DATA_SERVER_URL, "/openbis" + Constants.RAW_DATA_SERVER_URL })
+    { IRawDataService.SERVER_URL, "/openbis" + IRawDataService.SERVER_URL })
 public class RawDataServiceServer extends HttpInvokerServiceExporter
 {
     @Resource(name = Constants.PHOSPHONETX_RAW_DATA_SERVICE)
@@ -51,9 +51,11 @@ public class RawDataServiceServer extends HttpInvokerServiceExporter
         setService(service);
         setInterceptors(new Object[]
             { new ServiceExceptionTranslator() });
+        int majorVersion = service.getMajorVersion();
+        int minorVersion = service.getMinorVersion();
         RpcServiceInterfaceVersionDTO ifaceVersion =
-                new RpcServiceInterfaceVersionDTO("phosphonetx-raw-data",
-                        Constants.RAW_DATA_SERVER_URL, 1, 0);
+                new RpcServiceInterfaceVersionDTO(IRawDataService.SERVICE_NAME,
+                        IRawDataService.SERVER_URL, majorVersion, minorVersion);
         nameServer.addSupportedInterfaceVersion(ifaceVersion);
         super.afterPropertiesSet();
     }
diff --git a/rtd_phosphonetx/sourceTest/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiFacadeTest.java b/rtd_phosphonetx/sourceTest/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiFacadeTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..df0f329ec33dbefeaafe4d2a136d4d8565a19f18
--- /dev/null
+++ b/rtd_phosphonetx/sourceTest/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/api/v1/RawDataApiFacadeTest.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.openbis.plugin.phosphonetx.client.api.v1;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.IGeneralInformationService;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Project;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Role;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SpaceWithProjectsAndRoleAssignments;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.IRawDataService;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.DataStoreServerProcessingPluginInfo;
+import ch.systemsx.cisd.openbis.plugin.phosphonetx.shared.api.v1.dto.MsInjectionDataInfo;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class RawDataApiFacadeTest extends AssertJUnit
+{
+    private static final String SESSION_TOKEN = "Session-42";
+    
+    private Mockery context;
+    private IRawDataService rawDataService;
+    private IGeneralInformationService generalInfoService;
+    private IRawDataApiFacade facade;
+
+    @BeforeMethod
+    public void beforeMethod()
+    {
+        context = new Mockery();
+        rawDataService = context.mock(IRawDataService.class);
+        generalInfoService = context.mock(IGeneralInformationService.class);
+        facade = new RawDataApiFacade(rawDataService, generalInfoService, SESSION_TOKEN);
+    }
+    
+    @AfterMethod
+    public void afterMethod()
+    {
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testGetSessionToken()
+    {
+        assertEquals(SESSION_TOKEN, facade.getSessionToken());
+        
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testLogout()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(generalInfoService).logout(SESSION_TOKEN);
+                }
+            });
+        
+        facade.logout();
+        
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testListDataStoreServerProcessingPluginInfos()
+    {
+        final List<DataStoreServerProcessingPluginInfo> result =
+                new LinkedList<DataStoreServerProcessingPluginInfo>();
+        context.checking(new Expectations()
+            {
+                {
+                    one(rawDataService).listDataStoreServerProcessingPluginInfos(SESSION_TOKEN);
+                    will(returnValue(result));
+                }
+            });
+        
+        assertSame(result, facade.listDataStoreServerProcessingPluginInfos());
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public void testListRawDataSamples()
+    {
+        final List<MsInjectionDataInfo> result = new LinkedList<MsInjectionDataInfo>();
+        context.checking(new Expectations()
+            {
+                {
+                    one(rawDataService).listRawDataSamples(SESSION_TOKEN, "user1");
+                    will(returnValue(result));
+                }
+            });
+
+        assertSame(result, facade.listRawDataSamples("user1"));
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testProcessingRawData()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(rawDataService).processingRawData(SESSION_TOKEN, "user1", "key",
+                            new long[42], "type");
+                }
+            });
+
+        facade.processingRawData("user1", "key", new long[42], "type");
+        
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testListProjectsButNoUserRoles()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(generalInfoService).listNamedRoleSets(SESSION_TOKEN);
+                    will(returnValue(new HashMap<String, Set<Role>>()));
+                }
+            });
+        
+        try
+        {
+            facade.listProjects("user1");
+            fail("IllegalStateException expected");
+        } catch (IllegalStateException ex)
+        {
+            assertEquals("Role set USER not known.", ex.getMessage());
+        }
+        
+        context.assertIsSatisfied();
+    }
+    
+    @Test
+    public void testListProjects()
+    {
+        context.checking(new Expectations()
+        {
+            {
+                one(generalInfoService).listNamedRoleSets(SESSION_TOKEN);
+                HashMap<String, Set<Role>> sets = new HashMap<String, Set<Role>>();
+                HashSet<Role> set = new HashSet<Role>();
+                set.add(new Role("R1", true));
+                set.add(new Role("R2", false));
+                sets.put("USER", set);
+                will(returnValue(sets));
+                
+                one(generalInfoService).listSpacesWithProjectsAndRoleAssignments(SESSION_TOKEN, null);
+                SpaceWithProjectsAndRoleAssignments a = createSpace("A", "alpha", "beta");
+                a.add("user1", new Role("R1", true));
+                a.add("user1", new Role("R3", false));
+                SpaceWithProjectsAndRoleAssignments b = createSpace("B", "gamma");
+                b.add("user1", new Role("R2", true));
+                will(returnValue(Arrays.asList(a, b)));
+            }
+        });
+        
+        List<Project> projects = facade.listProjects("user1");
+        
+        assertEquals("[/A/alpha, /A/beta]", projects.toString());
+        context.assertIsSatisfied();
+    }
+    
+    private SpaceWithProjectsAndRoleAssignments createSpace(String spaceCode, String... projects)
+    {
+        SpaceWithProjectsAndRoleAssignments space = new SpaceWithProjectsAndRoleAssignments(spaceCode);
+        for (String project : projects)
+        {
+            space.add(new Project(spaceCode, project));
+        }
+        return space;
+    }
+}