diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/ISampleListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/ISampleListingQuery.java
index 3db8e1e751a7ad32c737410e17be91901dbf7d95..30a0d043196334c5e3b649a3d85c68525314b235 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/ISampleListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/ISampleListingQuery.java
@@ -41,9 +41,13 @@ public interface ISampleListingQuery extends BaseQuery
             + "s.registration_timestamp as s_registration_timestamp, "
             + "s.modification_timestamp as s_modification_timestamp, sp.code as sp_code, "
             + "st.id as st_id, st.code as st_code, pe.first_name as pe_first_name, "
-            + "pe.last_name as pe_last_name, pe.user_id as pe_user_id, pe.email as pe_email "
+            + "pe.last_name as pe_last_name, pe.user_id as pe_user_id, pe.email as pe_email, "
+            + "e.code as exp_code, p.code as proj_code, ps.code as proj_space_code "
             + "from samples as s join sample_types as st on s.saty_id = st.id "
             + "left join spaces as sp on s.space_id = sp.id "
+            + "left join experiments as e on s.expe_id = e.id "
+            + "left join projects as p on e.proj_id = p.id "
+            + "left join spaces as ps on p.space_id = ps.id "
             + "join persons as pe on s.pers_id_registerer = pe.id where s.id = any(?{1}) ", parameterBindings =
         { LongSetMapper.class }, fetchSize = FETCH_SIZE)
     public List<SampleRecord> listSamplesByIds(LongSet sampleIDs);
@@ -67,7 +71,7 @@ public interface ISampleListingQuery extends BaseQuery
     public List<SampleRelationshipRecord> getDescendants(Long relationshipID, LongSet sampleIDs);
 
     @Select(sql = "with recursive connected_relationships as (select * from sample_relationships "
-            + "where relationship_id = ?{1} and sample_id_parent = any(?{2}) "
+            + "where relationship_id = ?{1} and sample_id_child = any(?{2}) "
             + "union select sr.* from connected_relationships as cr "
             + "join sample_relationships as sr on cr.sample_id_parent = sr.sample_id_child) "
             + "select * from connected_relationships", parameterBindings =
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java
index 8389c544ac29e190cbf762b42527051a43bd66a9..53e28f8c2db5735cce07e4ed3ed95f334945609c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleLister.java
@@ -108,9 +108,11 @@ public class SampleLister implements ISampleLister
         {
             descendants = query.getChildren(getRelationShipType(), rootSampleIdSet);
         }
+        LongSet descendentIdSet = new LongOpenHashSet();
         for (SampleRelationshipRecord relationShip : descendants)
         {
             sampleIdSet.add(relationShip.sample_id_child);
+            descendentIdSet.add(relationShip.sample_id_child);
         }
         List<SampleRelationshipRecord> ancestors = Collections.emptyList();
         if (fetchOptions.contains(SampleFetchOption.ANCESTORS))
@@ -120,34 +122,72 @@ public class SampleLister implements ISampleLister
         {
             ancestors = query.getParents(getRelationShipType(), rootSampleIdSet);
         }
+        LongSet ancestorIdSet = new LongOpenHashSet();
         for (SampleRelationshipRecord relationShip : ancestors)
         {
             sampleIdSet.add(relationShip.sample_id_parent);
+            ancestorIdSet.add(relationShip.sample_id_parent);
         }
-        List<SampleRecord> list = query.listSamplesByIds(sampleIdSet);
         TableMap<Long, SampleRecord> sampleRecords =
-                new TableMap<Long, SampleRecord>(list, ID_EXTRACTOR);
+                getAllSamples(sampleIdSet, rootSampleIdSet, descendentIdSet, ancestorIdSet,
+                        fetchOptions);
         if (fetchOptions.contains(SampleFetchOption.PROPERTIES))
         {
             enrichWithProperties(sampleRecords, sampleIdSet);
         }
-        enrichWithDescendants(descendants, sampleRecords);
-        enrichWithAncestors(ancestors, sampleRecords);
+        enrichWithDescendants(descendants, sampleRecords,
+                fetchOptions.contains(SampleFetchOption.DESCENDANTS));
+        enrichWithAncestors(ancestors, sampleRecords,
+                fetchOptions.contains(SampleFetchOption.ANCESTORS));
         List<Sample> samples = new ArrayList<Sample>();
         for (Long rootSampleID : sampleIDs)
         {
             SampleRecord sampleRecord = sampleRecords.tryGet(rootSampleID);
             if (sampleRecord != null)
             {
-                samples.add(createSample(sampleRecord, fetchOptions));
+                samples.add(createSample(sampleRecord));
             }
         }
         Collections.sort(samples, SAMPLE_COMPARATOR);
         return samples;
     }
 
+    public TableMap<Long, SampleRecord> getAllSamples(LongSet sampleIdSet, LongSet rootSampleIdSet,
+            LongSet descendentIdSet, LongSet ancestorIdSet, EnumSet<SampleFetchOption> fetchOptions)
+    {
+        List<SampleRecord> list = query.listSamplesByIds(sampleIdSet);
+        TableMap<Long, SampleRecord> sampleRecords =
+                new TableMap<Long, SampleRecord>(list, ID_EXTRACTOR);
+        for (SampleRecord sampleRecord : sampleRecords)
+        {
+            sampleRecord.fetchOptions = createAppropriateFetchOptions(fetchOptions);
+            if (rootSampleIdSet.contains(sampleRecord.s_id))
+            {
+                if (fetchOptions.contains(SampleFetchOption.CHILDREN)
+                        || fetchOptions.contains(SampleFetchOption.DESCENDANTS))
+                {
+                    sampleRecord.fetchOptions.add(SampleFetchOption.CHILDREN);
+                }
+                if (fetchOptions.contains(SampleFetchOption.PARENTS)
+                        || fetchOptions.contains(SampleFetchOption.ANCESTORS))
+                {
+                    sampleRecord.fetchOptions.add(SampleFetchOption.PARENTS);
+                }
+            } else if (fetchOptions.contains(SampleFetchOption.ANCESTORS)
+                    && ancestorIdSet.contains(sampleRecord.s_id))
+            {
+                sampleRecord.fetchOptions.add(SampleFetchOption.PARENTS);
+            } else if (fetchOptions.contains(SampleFetchOption.DESCENDANTS)
+                    && descendentIdSet.contains(sampleRecord.s_id))
+            {
+                sampleRecord.fetchOptions.add(SampleFetchOption.CHILDREN);
+            }
+        }
+        return sampleRecords;
+    }
+
     public void enrichWithAncestors(List<SampleRelationshipRecord> ancestors,
-            TableMap<Long, SampleRecord> sampleRecords)
+            TableMap<Long, SampleRecord> sampleRecords, boolean allAncestors)
     {
         for (SampleRelationshipRecord ancestor : ancestors)
         {
@@ -158,6 +198,10 @@ public class SampleLister implements ISampleLister
                 if (child.parents == null)
                 {
                     child.parents = new LinkedList<SampleRecord>();
+                    if (allAncestors)
+                    {
+                        child.fetchOptions.add(SampleFetchOption.PARENTS);
+                    }
                 }
                 child.parents.add(parent);
             }
@@ -165,7 +209,7 @@ public class SampleLister implements ISampleLister
     }
 
     public void enrichWithDescendants(List<SampleRelationshipRecord> descendants,
-            TableMap<Long, SampleRecord> sampleRecords)
+            TableMap<Long, SampleRecord> sampleRecords, boolean allDescendants)
     {
         for (SampleRelationshipRecord descendant : descendants)
         {
@@ -176,15 +220,20 @@ public class SampleLister implements ISampleLister
                 if (parent.children == null)
                 {
                     parent.children = new LinkedList<SampleRecord>();
+                    if (allDescendants)
+                    {
+                        parent.fetchOptions.add(SampleFetchOption.CHILDREN);
+                    }
                 }
                 parent.children.add(child);
             }
         }
     }
 
-    private void enrichWithProperties(TableMap<Long, SampleRecord> sampleRecords, LongSet sampleIDs)
+    private void enrichWithProperties(TableMap<Long, SampleRecord> sampleRecords,
+            LongSet sampleIdSet)
     {
-        List<PropertyRecord> properties = query.getProperties(sampleIDs);
+        List<PropertyRecord> properties = query.getProperties(sampleIdSet);
         for (PropertyRecord propertyRecord : properties)
         {
             SampleRecord sampleRecord = sampleRecords.tryGet(propertyRecord.entity_id);
@@ -199,7 +248,7 @@ public class SampleLister implements ISampleLister
         }
     }
 
-    private Sample createSample(SampleRecord sampleRecord, EnumSet<SampleFetchOption> fetchOptions)
+    private Sample createSample(SampleRecord sampleRecord)
     {
         Sample.SampleInitializer initializer = new Sample.SampleInitializer();
         initializer.setId(sampleRecord.s_id);
@@ -221,6 +270,11 @@ public class SampleLister implements ISampleLister
         initializer.setRegistrationDetails(new EntityRegistrationDetails(detailsInitializer));
         initializer.setSampleTypeId(sampleRecord.st_id);
         initializer.setSampleTypeCode(sampleRecord.st_code);
+        if (sampleRecord.exp_code != null)
+        {
+            initializer.setExperimentIdentifierOrNull("/" + sampleRecord.proj_space_code + "/"
+                    + sampleRecord.proj_code + "/" + sampleRecord.exp_code);
+        }
         Map<String, String> properties = sampleRecord.properties;
         if (properties != null)
         {
@@ -229,36 +283,14 @@ public class SampleLister implements ISampleLister
                 initializer.putProperty(entry.getKey(), entry.getValue());
             }
         }
-        EnumSet<SampleFetchOption> rootFetchOptions = createAppropriateFetchOptions(fetchOptions);
-        if (fetchOptions.contains(SampleFetchOption.CHILDREN)
-                || fetchOptions.contains(SampleFetchOption.DESCENDANTS))
-        {
-            rootFetchOptions.add(SampleFetchOption.CHILDREN);
-        }
-        if (fetchOptions.contains(SampleFetchOption.PARENTS)
-                || fetchOptions.contains(SampleFetchOption.ANCESTORS))
-        {
-            rootFetchOptions.add(SampleFetchOption.PARENTS);
-        }
-        initializer.setRetrievedFetchOptions(rootFetchOptions);
+        initializer.setRetrievedFetchOptions(sampleRecord.fetchOptions);
         if (sampleRecord.children != null)
         {
-            EnumSet<SampleFetchOption> childrenOptions =
-                    createAppropriateFetchOptions(fetchOptions);
-            if (fetchOptions.contains(SampleFetchOption.DESCENDANTS))
-            {
-                childrenOptions.add(SampleFetchOption.CHILDREN);
-            }
-            initializer.setChildren(createChildren(sampleRecord.children, childrenOptions));
+            initializer.setChildren(createChildren(sampleRecord.children));
         }
         if (sampleRecord.parents != null)
         {
-            EnumSet<SampleFetchOption> parentsOptions = createAppropriateFetchOptions(fetchOptions);
-            if (fetchOptions.contains(SampleFetchOption.ANCESTORS))
-            {
-                parentsOptions.add(SampleFetchOption.PARENTS);
-            }
-            initializer.setParents(createParents(sampleRecord.parents, parentsOptions));
+            initializer.setParents(createParents(sampleRecord.parents));
         }
         return new Sample(initializer);
     }
@@ -271,25 +303,23 @@ public class SampleLister implements ISampleLister
                         : SampleFetchOption.BASIC);
     }
 
-    private List<Sample> createChildren(List<SampleRecord> childRecords,
-            EnumSet<SampleFetchOption> fetchOptions)
+    private List<Sample> createChildren(List<SampleRecord> childRecords)
     {
         List<Sample> children = new ArrayList<Sample>();
         for (SampleRecord childRecord : childRecords)
         {
-            children.add(createSample(childRecord, fetchOptions));
+            children.add(createSample(childRecord));
         }
         Collections.sort(children, SAMPLE_COMPARATOR);
         return children;
     }
 
-    private List<Sample> createParents(List<SampleRecord> parentRecords,
-            EnumSet<SampleFetchOption> fetchOptions)
+    private List<Sample> createParents(List<SampleRecord> parentRecords)
     {
         List<Sample> parents = new ArrayList<Sample>();
         for (SampleRecord parentRecord : parentRecords)
         {
-            parents.add(createSample(parentRecord, fetchOptions));
+            parents.add(createSample(parentRecord));
         }
         Collections.sort(parents, SAMPLE_COMPARATOR);
         return parents;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleRecord.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleRecord.java
index c66cec766fcd28ef2b80cea4500ee047e69e5450..717e4a743b0432f0776165e3521272addbb53b22 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleRecord.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/fetchoptions/samplelister/SampleRecord.java
@@ -17,9 +17,12 @@
 package ch.systemsx.cisd.openbis.generic.server.business.bo.fetchoptions.samplelister;
 
 import java.util.Date;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
 
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SampleFetchOption;
+
 /**
  * @author Franz-Josef Elmer
  */
@@ -50,10 +53,18 @@ public class SampleRecord
 
     public String pe_email;
 
+    public String exp_code;
+
+    public String proj_code;
+
+    public String proj_space_code;
+
     public List<SampleRecord> children;
 
     public List<SampleRecord> parents;
 
     public Map<String, String> properties;
 
+    public EnumSet<SampleFetchOption> fetchOptions;
+
 }
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
index 449004d45b1dea2d98ba6c6aaec32a2b5c70de8f..91b3e8dfbbd95157ca8e2ed9c4ac0d3e9088435f 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/systemtest/api/v1/GeneralInformationServiceTest.java
@@ -191,6 +191,149 @@ public class GeneralInformationServiceTest extends SystemTestCase
         assertEntities("[]", samples);
     }
 
+    @Test
+    public void testSearchForSamplesWithParents()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.TYPE,
+                "DILUTION_PLATE"));
+
+        EnumSet<SampleFetchOption> fetchOptions =
+                EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.PARENTS);
+        List<Sample> samples =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria,
+                        fetchOptions);
+
+        assertEntities("[/CISD/3V-125, /CISD/3V-126, /CISD/DP1-A, /CISD/DP1-B, /CISD/DP2-A, /DP]",
+                samples);
+        assertEquals(fetchOptions, samples.get(0).getRetrievedFetchOptions());
+        List<Sample> parents = samples.get(0).getParents();
+        assertEntities("[/CISD/MP002-1]", parents);
+        assertEquals("MP002-1", parents.get(0).getCode());
+        assertEquals(EnumSet.of(SampleFetchOption.PROPERTIES), parents.get(0)
+                .getRetrievedFetchOptions());
+        assertEquals("{PLATE_GEOMETRY=384_WELLS_16X24}", parents.get(0).getProperties().toString());
+    }
+
+    @Test
+    public void testSearchForSamplesWithParentsButNoProperties()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.TYPE,
+                "DILUTION_PLATE"));
+
+        EnumSet<SampleFetchOption> fetchOptions = EnumSet.of(SampleFetchOption.PARENTS);
+        List<Sample> samples =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria,
+                        fetchOptions);
+
+        assertEntities("[/CISD/3V-125, /CISD/3V-126, /CISD/DP1-A, /CISD/DP1-B, /CISD/DP2-A, /DP]",
+                samples);
+        assertEquals(EnumSet.of(SampleFetchOption.BASIC, SampleFetchOption.PARENTS), samples.get(0)
+                .getRetrievedFetchOptions());
+        assertEquals(null, samples.get(0).getExperimentIdentifierOrNull());
+        assertEquals("{}", samples.get(0).getProperties().toString());
+        List<Sample> parents = samples.get(0).getParents();
+        assertEntities("[/CISD/MP002-1]", parents);
+        assertEquals("MP002-1", parents.get(0).getCode());
+        assertEquals(EnumSet.of(SampleFetchOption.BASIC), parents.get(0).getRetrievedFetchOptions());
+        assertEquals("{}", parents.get(0).getProperties().toString());
+    }
+
+    @Test
+    public void testSearchForSamplesWithParentsAndDescendentsButNoProperties()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.TYPE,
+                "DILUTION_PLATE"));
+
+        EnumSet<SampleFetchOption> fetchOptions =
+                EnumSet.of(SampleFetchOption.PARENTS, SampleFetchOption.DESCENDANTS);
+        List<Sample> samples =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria,
+                        fetchOptions);
+
+        assertEntities("[/CISD/3V-125, /CISD/3V-126, /CISD/DP1-A, /CISD/DP1-B, /CISD/DP2-A, /DP]",
+                samples);
+        assertEquals(EnumSet.of(SampleFetchOption.BASIC, SampleFetchOption.PARENTS,
+                SampleFetchOption.CHILDREN), samples.get(0).getRetrievedFetchOptions());
+        assertEquals(null, samples.get(0).getExperimentIdentifierOrNull());
+        assertEquals("{}", samples.get(0).getProperties().toString());
+        List<Sample> parents = samples.get(0).getParents();
+        assertEntities("[/CISD/MP002-1]", parents);
+        assertEquals("MP002-1", parents.get(0).getCode());
+        assertEquals(EnumSet.of(SampleFetchOption.BASIC), parents.get(0).getRetrievedFetchOptions());
+        assertEquals("{}", parents.get(0).getProperties().toString());
+        List<Sample> children = samples.get(0).getChildren();
+        assertEntities("[/CISD/3VCP5, /CISD/3VCP6, /CISD/3VCP7, /CISD/3VCP8]", children);
+        assertEquals("3VCP5", children.get(0).getCode());
+        assertEquals(EnumSet.of(SampleFetchOption.BASIC, SampleFetchOption.CHILDREN),
+                children.get(0).getRetrievedFetchOptions());
+        assertEquals("{}", children.get(0).getProperties().toString());
+        assertEntities("[]", children.get(0).getChildren());
+    }
+
+    @Test
+    public void testSearchForSamplesWithAncestors()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE,
+                "3VCP*"));
+
+        EnumSet<SampleFetchOption> fetchOptions =
+                EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.ANCESTORS);
+        List<Sample> samples =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria,
+                        fetchOptions);
+
+        assertEntities("[/CISD/3VCP5, /CISD/3VCP6, /CISD/3VCP7, /CISD/3VCP8]", samples);
+        assertEquals(EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.PARENTS), samples
+                .get(0).getRetrievedFetchOptions());
+        assertEquals("/CISD/NEMO/EXP10", samples.get(0).getExperimentIdentifierOrNull());
+        List<Sample> parents = samples.get(0).getParents();
+        assertEntities("[/CISD/3V-125]", parents);
+        assertEquals("3V-125", parents.get(0).getCode());
+        assertEquals(EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.PARENTS), parents
+                .get(0).getRetrievedFetchOptions());
+        List<Sample> grandParents = parents.get(0).getParents();
+        assertEntities("[/CISD/MP002-1]", grandParents);
+        assertEquals("MP002-1", grandParents.get(0).getCode());
+        assertEquals(EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.PARENTS),
+                grandParents.get(0).getRetrievedFetchOptions());
+        assertEquals("{PLATE_GEOMETRY=384_WELLS_16X24}", grandParents.get(0).getProperties()
+                .toString());
+        assertEntities("[]", grandParents.get(0).getParents());
+    }
+
+    @Test
+    public void testSearchForSamplesWithDescendants()
+    {
+        SearchCriteria searchCriteria = new SearchCriteria();
+        searchCriteria.addMatchClause(MatchClause.createAttributeMatch(MatchClauseAttribute.CODE,
+                "MP002-1 "));
+
+        EnumSet<SampleFetchOption> fetchOptions =
+                EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.DESCENDANTS);
+        List<Sample> samples =
+                generalInformationService.searchForSamples(sessionToken, searchCriteria,
+                        fetchOptions);
+
+        assertEntities("[/CISD/MP002-1]", samples);
+        assertEquals(EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.CHILDREN), samples
+                .get(0).getRetrievedFetchOptions());
+        List<Sample> children = samples.get(0).getChildren();
+        assertEntities("[/CISD/3V-125, /CISD/3V-126]", children);
+        assertEquals(EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.CHILDREN), children
+                .get(0).getRetrievedFetchOptions());
+        List<Sample> grandChildren = children.get(0).getChildren();
+        assertEntities("[/CISD/3VCP5, /CISD/3VCP6, /CISD/3VCP7, /CISD/3VCP8]", grandChildren);
+        assertEquals("3VCP5", grandChildren.get(0).getCode());
+        assertEquals(EnumSet.of(SampleFetchOption.PROPERTIES, SampleFetchOption.CHILDREN),
+                grandChildren.get(0).getRetrievedFetchOptions());
+        assertEquals("{}", grandChildren.get(0).getProperties().toString());
+        assertEntities("[]", grandChildren.get(0).getChildren());
+    }
+
     @Test
     public void testListSamplesForExperiment()
     {