diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..65e5de115332bd94679987607c239eb025844785
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServer.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2008 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.generic.server;
+
+import java.util.List;
+
+import ch.systemsx.cisd.authentication.ISessionManager;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister;
+import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory;
+import ch.systemsx.cisd.openbis.generic.shared.ITrackingServer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ListOrSearchSampleCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingSampleCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+
+public final class TrackingServer extends AbstractServer<ITrackingServer> implements
+        ITrackingServer
+{
+    private final ICommonBusinessObjectFactory businessObjectFactory;
+
+    public TrackingServer(final ISessionManager<Session> sessionManager,
+            final IDAOFactory daoFactory, final ICommonBusinessObjectFactory businessObjectFactory)
+    {
+        super(sessionManager, daoFactory);
+        this.businessObjectFactory = businessObjectFactory;
+    }
+
+    ICommonBusinessObjectFactory getBusinessObjectFactory()
+    {
+        return businessObjectFactory;
+    }
+
+    // private static UserFailureException createUserFailureException(final DataAccessException ex)
+    // {
+    // return new UserFailureException(ex.getMostSpecificCause().getMessage(), ex);
+    // }
+
+    //
+    // IInvocationLoggerFactory
+    //
+
+    /**
+     * Creates a logger used to log invocations of objects of this class.
+     */
+    public final ITrackingServer createLogger(final boolean invocationSuccessful,
+            final long elapsedTime)
+    {
+        return new TrackingServerLogger(getSessionManager(), invocationSuccessful, elapsedTime);
+    }
+
+    //
+    // ITrackingServer
+    //
+
+    public List<ExternalData> listDataSets(String sessionToken, TrackingDataSetCriteria criteria)
+    {
+        // TODO 2009-11-06, Piotr Buczek: implement
+        return null;
+    }
+
+    public List<Sample> listSamples(String sessionToken, TrackingSampleCriteria criteria)
+    {
+        final Session session = getSession(sessionToken);
+        final ISampleLister sampleLister = businessObjectFactory.createSampleLister(session);
+        return sampleLister.list(new ListOrSearchSampleCriteria(criteria));
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServerLogger.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b5598e4b18884be1b58e0fffac5056ffd0a285a
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServerLogger.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008 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.generic.server;
+
+import java.util.List;
+
+import ch.systemsx.cisd.authentication.ISessionManager;
+import ch.systemsx.cisd.openbis.generic.shared.ITrackingServer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingSampleCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+
+/**
+ * Logger class for {@link TrackingServer} which creates readable logs of method invocations.
+ * 
+ * @author Piotr Buczek
+ */
+final class TrackingServerLogger extends AbstractServerLogger implements ITrackingServer
+{
+    /**
+     * Creates an instance for the specified session manager, invocation status and elapsed time.
+     * The session manager is used to retrieve user information which will be a part of the log
+     * message.
+     */
+    TrackingServerLogger(final ISessionManager<Session> sessionManager,
+            final boolean invocationSuccessful, final long elapsedTime)
+    {
+        super(sessionManager, invocationSuccessful, elapsedTime);
+    }
+
+    //
+    // ITrackingServer
+    //
+
+    public List<ExternalData> listDataSets(String sessionToken, TrackingDataSetCriteria criteria)
+    {
+        logTracking(sessionToken, "list_data_sets", "SAMPLE_TYPE(%s) LAST_DATASET_ID(%s)", criteria
+                .getConnectedSampleTypeCode(), criteria.getLastSeenDataSetId());
+        return null;
+    }
+
+    public List<Sample> listSamples(String sessionToken, TrackingSampleCriteria criteria)
+    {
+        logTracking(sessionToken, "list_samples", "SAMPLE_TYPE(%s) LAST_SAMPLE_ID(%s)", criteria
+                .getSampleTypeCode(), criteria.getLastSeenSampleId());
+        return null;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServiceServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServiceServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..57b7cb12bf5f924cd2a06debd86b87f4745f1da6
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/TrackingServiceServer.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 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.generic.server;
+
+import javax.annotation.Resource;
+
+import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import ch.systemsx.cisd.openbis.generic.shared.ITrackingServer;
+import ch.systemsx.cisd.openbis.generic.shared.ResourceNames;
+
+/**
+ * @author Piotr Buczek
+ */
+@Controller
+@RequestMapping(
+    { "/rmi-tracking", "/openbis/rmi-tracking" })
+public class TrackingServiceServer extends HttpInvokerServiceExporter
+{
+    @Resource(name = ResourceNames.TRACKING_SERVER)
+    private ITrackingServer server;
+
+    @Override
+    public void afterPropertiesSet()
+    {
+        setServiceInterface(ITrackingServer.class);
+        setService(server);
+        super.afterPropertiesSet();
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java
index ddc9fb91876d95595df93131ab42befe95e8d2a5..5d54cbaa5c18f64814142a1b5fe00206dd3029ac 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java
@@ -158,6 +158,19 @@ public interface ISampleListingQuery extends TransactionQuery, IPropertyListingQ
             + "   from samples s where s.samp_id_part_of=?{1}", fetchSize = FETCH_SIZE)
     public DataIterator<SampleRecord> getSamplesForContainer(long sampleContainerId);
 
+    //
+    // Samples of type
+    //
+
+    /**
+     * Returns all samples for the given <var>sampleTypeId</var>.
+     */
+    @Select(sql = "select s.id, s.perm_id, s.code, s.expe_id, s.grou_id, s.dbin_id, "
+            + "       s.registration_timestamp, s.pers_id_registerer, "
+            + "       s.samp_id_generated_from, s.samp_id_part_of, s.saty_id, s.inva_id "
+            + "   from samples s where s.saty_id=?{1} order by s.code", fetchSize = FETCH_SIZE)
+    public DataIterator<SampleRecord> getSamplesForSampleType(long sampleTypeId);
+
     //
     // Shared samples
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java
index 9a50a5b3e3f4a42ccc4554b85841c1e7929a9910..ff3dab63cbf268551c999998826577747445a136 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/SampleListingWorker.java
@@ -31,6 +31,7 @@ import org.apache.commons.lang.time.StopWatch;
 import org.apache.log4j.Logger;
 
 import ch.rinn.restrictions.Friend;
+import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.common.EntityPropertiesEnricher;
@@ -207,6 +208,7 @@ final class SampleListingWorker
         retrievePrimaryBasicSamples(tryGetIteratorForSharedSamples());
         retrievePrimaryBasicSamples(tryGetIteratorForExperimentSamples());
         retrievePrimaryBasicSamples(tryGetIteratorForContainedSamples());
+        retrievePrimaryBasicSamples(tryGetIteratorForTrackedSamples());
         if (operationLog.isDebugEnabled())
         {
             watch.stop();
@@ -386,6 +388,32 @@ final class SampleListingWorker
         }
     }
 
+    private Iterable<SampleRecord> tryGetIteratorForTrackedSamples()
+    {
+        final String sampleTypeCode = criteria.getSampleTypeCode();
+        if (sampleTypeCode == null)
+        {
+            return null;
+        }
+        SampleType sampleTypeOrNull = null;
+        for (SampleType sampleType : sampleTypes.values())
+        {
+            if (sampleType.getCode().equals(sampleTypeCode))
+            {
+                sampleTypeOrNull = sampleType;
+            }
+        }
+        if (sampleTypeOrNull != null)
+        {
+            return query.getSamplesForSampleType(sampleTypeOrNull.getId());
+        } else
+        {
+            throw UserFailureException
+                    .fromTemplate("No sample type with code '%s' could be found in the database.",
+                            sampleTypeCode);
+        }
+    }
+
     private void retrievePrimaryBasicSamples(final Iterable<SampleRecord> sampleIteratorOrNull)
     {
         assert sampleList != null;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ITrackingServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ITrackingServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..daa92d1625c927a5109a50b83c3927a893e85761
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ITrackingServer.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 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.generic.shared;
+
+import java.util.List;
+
+import org.springframework.transaction.annotation.Transactional;
+
+import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RoleSet;
+import ch.systemsx.cisd.openbis.generic.shared.authorization.annotation.RolesAllowed;
+import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingSampleCriteria;
+
+/**
+ * Definition of the client-server interface.
+ * 
+ * @author Piotr Buczek
+ */
+public interface ITrackingServer extends IServer
+{
+
+    /**
+     * Lists samples using given criteria.
+     * 
+     * @return a sorted list of {@link Sample}.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.INSTANCE_ADMIN)
+    public List<Sample> listSamples(final String sessionToken, final TrackingSampleCriteria criteria);
+
+    /**
+     * For given sample {@link TechId} returns the corresponding list of {@link ExternalData}.
+     * 
+     * @return a sorted list of {@link ExternalData}.
+     */
+    @Transactional(readOnly = true)
+    @RolesAllowed(RoleSet.INSTANCE_ADMIN)
+    public List<ExternalData> listDataSets(final String sessionToken,
+            final TrackingDataSetCriteria criteria);
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java
index d65a4b325dfcadf538aa97ff4234c13a2618341b..27153139372ce58c85be8c6e14946252bdccbe50 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ResourceNames.java
@@ -48,4 +48,6 @@ public final class ResourceNames
     public final static String COMMON_SERVICE = "common-service";
 
     public final static String COMMON_SERVER = "common-server";
+
+    public final static String TRACKING_SERVER = "tracking-server";
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ListOrSearchSampleCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ListOrSearchSampleCriteria.java
index 1e051492733e1cae2aac540d1613fdd7a13d1ad2..bd3914502a0c4e00fecbfc705d23d6e9b789249b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ListOrSearchSampleCriteria.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ListOrSearchSampleCriteria.java
@@ -21,7 +21,8 @@ import java.util.Collection;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 
 /**
- * Extended {@link ListSampleCriteria} with 4th filter option for detailed sample search.<br>
+ * Extended {@link ListSampleCriteria} with 4th filter option for detailed sample search and 5th
+ * option for tracking samples.<br>
  * <br>
  * NOTE: not serializable
  * 
@@ -33,6 +34,8 @@ public final class ListOrSearchSampleCriteria extends ListSampleCriteria
 
     private ListSampleCriteria listCriteria;
 
+    private TrackingSampleCriteria trackingCriteria;
+
     private Collection<Long> sampleIds;
 
     /** Creates criteria that delegates to given {@link ListSampleCriteria}. */
@@ -42,6 +45,13 @@ public final class ListOrSearchSampleCriteria extends ListSampleCriteria
         this.listCriteria = listCriteria;
     }
 
+    /** Creates criteria that delegates to given {@link TrackingSampleCriteria}. */
+    public ListOrSearchSampleCriteria(TrackingSampleCriteria trackingCriteria)
+    {
+        assert trackingCriteria != null;
+        this.trackingCriteria = trackingCriteria;
+    }
+
     /** Creates criteria for detailed search of samples with given ids. */
     public ListOrSearchSampleCriteria(final Collection<Long> sampleIds)
     {
@@ -56,7 +66,19 @@ public final class ListOrSearchSampleCriteria extends ListSampleCriteria
         return sampleIds;
     }
 
-    // delegation
+    // delegation to TrackingSampleCriteria
+
+    public String getSampleTypeCode()
+    {
+        return trackingCriteria == null ? null : trackingCriteria.getSampleTypeCode();
+    }
+
+    public int getLastSeenSampleId()
+    {
+        return trackingCriteria == null ? null : trackingCriteria.getLastSeenSampleId();
+    }
+
+    // delegation to ListSampleCriteria
 
     @Override
     public TechId getContainerSampleId()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleParentWithDerived.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleParentWithDerived.java
index 8c965c84cf3ca568be41e41da51b1cf00f69b6aa..fe023938f512dc217ed934308caa415162af854b 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleParentWithDerived.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/SampleParentWithDerived.java
@@ -16,8 +16,9 @@
 
 package ch.systemsx.cisd.openbis.generic.shared.basic.dto;
 
-import com.google.gwt.user.client.rpc.IsSerializable;
+import java.io.Serializable;
 
+import com.google.gwt.user.client.rpc.IsSerializable;
 
 /**
  * A <code>SampleParentWithDerived</code> encapsulates a <code>Sample</code> (the parent) and its
@@ -25,8 +26,10 @@ import com.google.gwt.user.client.rpc.IsSerializable;
  * 
  * @author Christian Ribeaud
  */
-public final class SampleParentWithDerived implements IsSerializable
+public final class SampleParentWithDerived implements IsSerializable, Serializable
 {
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
     /**
      * The parent <code>Sample</code>.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TrackingDataSetCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TrackingDataSetCriteria.java
new file mode 100644
index 0000000000000000000000000000000000000000..7eb7f31088cfeabda1b3e54c5c991b991c51fa7f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TrackingDataSetCriteria.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 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.generic.shared.basic.dto;
+
+import java.io.Serializable;
+
+import com.google.gwt.user.client.rpc.IsSerializable;
+
+/**
+ * Criteria for tracking <i>data sets</i> connected to samples of a particular type with technical
+ * id bigger than the specified one.
+ * <p>
+ * Connected samples should be loaded as well as their parent and container samples according to
+ * {@link SampleType} hierarchy depths. All referenced samples should have all properties loaded.
+ * 
+ * @author Piotr Buczek
+ */
+// NOTE: It doesn't implement IsSerializable as it is not supposed to be used on the GWT client side
+public class TrackingDataSetCriteria implements IsSerializable, Serializable
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private final String connectedSampleTypeCode;
+
+    private int lastSeenDataSetId;
+
+    public TrackingDataSetCriteria(String connectedSampleTypeCode, int lastSeenDataSetId)
+    {
+        this.lastSeenDataSetId = lastSeenDataSetId;
+        this.connectedSampleTypeCode = connectedSampleTypeCode;
+    }
+
+    public String getConnectedSampleTypeCode()
+    {
+        return connectedSampleTypeCode;
+    }
+
+    public int getLastSeenDataSetId()
+    {
+        return lastSeenDataSetId;
+    }
+
+    public void setLastSeenDataSetId(int lastSeenDataSetId)
+    {
+        this.lastSeenDataSetId = lastSeenDataSetId;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TrackingSampleCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TrackingSampleCriteria.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5d5191cf8556fc6c6b4b5675cc34ca4c8b3c43f
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TrackingSampleCriteria.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 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.generic.shared.basic.dto;
+
+import java.io.Serializable;
+
+/**
+ * Criteria for tracking <i>samples</i> of a particular type with technical id bigger than the
+ * specified one.
+ * <p>
+ * Parent and Container samples should be loaded according to {@link SampleType} hierarchy depths.
+ * All referenced samples should have all properties loaded.
+ * 
+ * @author Piotr Buczek
+ */
+// NOTE: It doesn't implement IsSerializable as it is not supposed to be used on the GWT client side
+public class TrackingSampleCriteria implements Serializable
+{
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private final String sampleTypeCode;
+
+    private int lastSeenSampleId;
+
+    public TrackingSampleCriteria(String sampleTypeCode, int lastSeenSampleId)
+    {
+        this.sampleTypeCode = sampleTypeCode;
+        this.lastSeenSampleId = lastSeenSampleId;
+    }
+
+    public String getSampleTypeCode()
+    {
+        return sampleTypeCode;
+    }
+
+    public int getLastSeenSampleId()
+    {
+        return lastSeenSampleId;
+    }
+
+    public void setLastSeenSampleId(int lastSeenSampleId)
+    {
+        this.lastSeenSampleId = lastSeenSampleId;
+    }
+
+}
diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml
index 9b10be83ea9da2c18504ee5fa695d239ab6401c5..2909c52ffcbb8f604efd10bc14ce48c918fae961 100644
--- a/openbis/source/java/genericApplicationContext.xml
+++ b/openbis/source/java/genericApplicationContext.xml
@@ -90,6 +90,16 @@
         <property name="cifexRecipient" value="${cifex-recipient}"/>
     </bean>
     
+    <!-- 
+        // Tracking
+    -->
+    
+    <bean id="tracking-server" class="ch.systemsx.cisd.openbis.generic.server.TrackingServer">
+        <constructor-arg ref="session-manager" />
+        <constructor-arg ref="dao-factory" />
+        <constructor-arg ref="common-business-object-factory" />
+    </bean>
+    
     <!-- 
         // ETL Service with interceptors for translating results
     -->
diff --git a/openbis/source/java/service.properties b/openbis/source/java/service.properties
index 24e191cac09564a27752a6cde5cad841a1cddb98..57a3d562d3ecb7553ec36e2a90ee5785b2e11e64 100644
--- a/openbis/source/java/service.properties
+++ b/openbis/source/java/service.properties
@@ -1,7 +1,7 @@
 authentication-service = dummy-authentication-service
 
 # The time after which an inactive session is expired by the service (in minutes).
-session-timeout = 720
+session-timeout = 720 
 
 # Authorization
 # Supported: 'no-authorization' and 'active-authorization'
@@ -15,7 +15,7 @@ database.create-from-scratch = false
 # For debugging set this value to true.
 database.script-single-step-mode = false
 database.url-host-part =
-database.kind = dev
+database.kind = test
 # database.kind = system_test
 # database.kind = system_test_strict
 # database.kind = system_test_plates_on_demand
@@ -31,11 +31,12 @@ crowd.application.name = lims
 crowd.application.password =
 
 # The database instance local unique identifier. Used when the new database is created.
-database-instance = CISD
+database-instance = CISD 
+
 
 # Base URL of the Data Store Server. 
 # Will be used only for data sets registered in an openBIS server version before 14.04.2009 (or revision 10665)
-data-store-server-base-url = 
+data-store-server-base-url = http://localhost:8889/data_store
 
 # The URL of the CIFEX server
 cifex-url = https://cifex.ethz.ch:443
@@ -51,6 +52,7 @@ hibernate.search.index-base = ./targets/indices-${database.kind}
 # One of NO_INDEX, SKIP_IF_MARKER_FOUND, INDEX_FROM_SCRATCH.
 # If not specified, default (SKIP_IF_MARKER_FOUND) is taken.
 hibernate.search.index-mode = SKIP_IF_MARKER_FOUND
+#hibernate.search.index-mode = INDEX_FROM_SCRATCH
 # Defines the maximum number of elements indexed before flushing the transaction-bound queue.
 # Default is 1000.
 hibernate.search.batch-size = 1000
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/OpenbisClientTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/OpenbisClientTest.java
index c9a155199feb7004c227aa2d7db7535cbd4b499e..75b4dbbdaa28586893bfc0abbd25be82aa64bc5d 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/OpenbisClientTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/OpenbisClientTest.java
@@ -1,12 +1,22 @@
 package ch.systemsx.cisd.openbis.generic;
 
+import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
+
 import ch.systemsx.cisd.common.spring.HttpInvokerUtils;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
+import ch.systemsx.cisd.openbis.generic.shared.ITrackingServer;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ExternalData;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Sample;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleParentWithDerived;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingDataSetCriteria;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TrackingSampleCriteria;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SessionContextDTO;
 import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer;
 
@@ -30,43 +40,97 @@ import ch.systemsx.cisd.openbis.plugin.generic.shared.IGenericServer;
  * Demo of the openBIS client which uses HTTPInvoker. This test is not run automatically.
  * 
  * @author Tomasz Pylak
+ * @author Piotr Buczek
  */
 public class OpenbisClientTest
 {
-    public static void main(String[] args)
+    private static final String USER_ID = "test";
 
-    {
-        String userId = "user";
-        String userPassword = "password";
+    private static final String USER_PASSWORD = "test";
 
-        String serverURL = "http://localhost:8888/openbis";
+    private static final String SERVER_URL = "http://localhost:8888/openbis";
 
-        String commonServerPath = "rmi-common";// CommonServiceServer
-        ICommonServer commonServer =
+    // CommonServiceServer
+    private static final String COMMON_SERVICE_PATH = SERVER_URL + "/rmi-common";
 
-        HttpInvokerUtils.createServiceStub(ICommonServer.class, serverURL + "/"
+    // GenericServiceServer
+    private static final String GENERIC_SERVICE_PATH = SERVER_URL + "/rmi-plugin-generic";
 
-        + commonServerPath, 5);
-        SessionContextDTO session = commonServer.tryToAuthenticate(userId, userPassword);
-        List<Person> persons = commonServer.listPersons(session.getSessionToken());
+    // TrackingServiceServer
+    private static final String TRACKING_SERVICE_PATH = SERVER_URL + "/rmi-tracking";
+
+    public static void main(String[] args)
+    {
+        testCommonServerService(COMMON_SERVICE_PATH);
+        testGenericServerService(GENERIC_SERVICE_PATH);
+        testTrackingServerService(TRACKING_SERVICE_PATH);
+    }
 
+    private static void testCommonServerService(String serviceURL)
+    {
+        System.out.println("TEST CommonServerService: " + serviceURL);
+        ICommonServer commonServer =
+                HttpInvokerUtils.createServiceStub(ICommonServer.class, serviceURL, 5);
+        SessionContextDTO session = commonServer.tryToAuthenticate(USER_ID, USER_PASSWORD);
+
+        List<Person> persons = commonServer.listPersons(session.getSessionToken());
         for (Person p : persons)
         {
-
             System.out.println(p.getUserId());
         }
+    }
 
-        String genericServerPath = "rmi-plugin-generic"; // GenericServiceServer
-
+    private static void testGenericServerService(String serviceURL)
+    {
+        System.out.println("\nTEST GenericServerService: " + serviceURL);
         IGenericServer genericServer =
-
-        HttpInvokerUtils.createServiceStub(IGenericServer.class, serverURL + "/"
-
-        + genericServerPath, 5);
-        SessionContextDTO sessionGeneric = genericServer.tryToAuthenticate(userId, userPassword);
+                HttpInvokerUtils.createServiceStub(IGenericServer.class, serviceURL, 5);
+        SessionContextDTO session = genericServer.tryToAuthenticate(USER_ID, USER_PASSWORD);
 
         SampleParentWithDerived sampleInfo =
-                genericServer.getSampleInfo(sessionGeneric.getSessionToken(), new TechId(1L));
+                genericServer.getSampleInfo(session.getSessionToken(), new TechId(1L));
         System.out.println(sampleInfo.getParent().getCode());
     }
+
+    private static void testTrackingServerService(String serviceURL)
+    {
+        System.out.println("\nTEST TrackingServerService: " + serviceURL);
+        ITrackingServer trackingServer =
+                HttpInvokerUtils.createServiceStub(ITrackingServer.class, serviceURL, 5);
+        SessionContextDTO session = trackingServer.tryToAuthenticate(USER_ID, USER_PASSWORD);
+
+        final String sampleTypeCode = "CELL_PLATE";
+        final int lastSeenSampleId = 0;
+        final int lastSeenDataSetId = 0;
+
+        final TrackingSampleCriteria sampleCriteria =
+                new TrackingSampleCriteria(sampleTypeCode, lastSeenSampleId);
+        final List<Sample> samples =
+                trackingServer.listSamples(session.getSessionToken(), sampleCriteria);
+        outputFoundEntities(samples, EntityKind.SAMPLE);
+
+        final TrackingDataSetCriteria dataSetCriteria =
+                new TrackingDataSetCriteria(sampleTypeCode, lastSeenDataSetId);
+        final List<ExternalData> dataSets =
+                trackingServer.listDataSets(session.getSessionToken(), dataSetCriteria);
+        outputFoundEntities(dataSets, EntityKind.DATA_SET);
+    }
+
+    private static void outputFoundEntities(List<? extends IEntityInformationHolder> entities,
+            EntityKind entityKind)
+    {
+        if (entities == null || entities.size() == 0)
+        {
+            System.out.println(String.format("No %ss found.", entityKind.getDescription()));
+        } else
+        {
+            List<String> codes = new ArrayList<String>(entities.size());
+            for (IEntityInformationHolder entity : entities)
+            {
+                codes.add(entity.getCode());
+            }
+            System.out.println(String.format("Found %d %ss: %s", codes.size(), entityKind
+                    .getDescription(), StringUtils.join(codes, ", ")));
+        }
+    }
 }