Troubles setting a sample via Jython Dropbox

Hi folks,

as I try to switch more Jython Dropboxes to the V3 version of the API, I still have trouble finding the relevant methods.
Now, I have a very basic dropbox with a folder named after a sample code. The Dropbox shall check for the sample and attach the folder as a new dataset.


from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.fetchoptions import (
    SampleFetchOptions,
)
from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.search import SampleSearchCriteria
from ch.systemsx.cisd.openbis.dss.generic.shared import ServiceProvider


def process(transaction):
    
    service = ServiceProvider.getV3ApplicationService()
    sessionToken = transaction.getOpenBisServiceSessionToken()
    
    searchCriteria = SampleSearchCriteria()
    searchCriteria.withCode().thatEquals(transaction.getIncoming().getName())

    fetchOptions = SampleFetchOptions()
    fetchOptions.withProperties()
    fetchOptions.withSpace()
    

    results = service.searchSamples(
        sessionToken, searchCriteria, fetchOptions
    ).getObjects()

    

    dataSet = transaction.createNewDataSet()
    dataSet.setDataSetType("ATTACHMENT")
    dataSet.setPropertyValue("$NAME", "Microscopy images")

    transaction.moveFile(transaction.getIncoming().getAbsolutePath(), dataSet)
    dataSet.setSample(results[0])

Upon uploading the folder, the Dropbox monitor shows an error for the very last line:

TypeError: setSample(): 1st arg can’t be coerced to ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v2.ISampleImmutable

I basically get the message, but nevertheless, I don’t get what to pass there.

“results[0]” was my final try. I started with the Identifier I got back via


results[0].getIdentifier()

Out of sheer desperation I also tried


results[0].getIdentifier().toString()
results[0].getIdentifier().toString().encode(“utf-8”)
transaction.getIncoming().getName()

all giving the same error…

Additionally, what would be the method to look up the sample by PermId since Codes can exist in other spaces, too, as I understood?
Help is appreciated since I already spent quite some time figuring out the proper Java methods.

Thanks and cheers!

Hello

The problem in the code is that the data set you are creating is from the V2 API and you are trying to pass it an object from the V3 API. They are incompatible. To make your code work, I would suggest something like this:

sample_immutable = transaction.getSampleForUpdate(results[0].getIdentifier().toString())
dataSet.setSample(sample_immutable)

This should fix the error you have reported. Please let us know if it works for you.
Cheers,
Viktor

1 Like

Thanks Viktor,

works as advertised!

Regards,
Volker

Hi Viktor,

I want to extend the example a little bit since it is kind of a prototype for many (dropboxes and people):
Not only do I want to put a DataSet to a sample as before, I also want to create a sample, of a specific type first.
I know how to tackle that with the V2 API but adjusting to V3, I followed the procedure at https://unlimited.ethz.ch/display/openBISDoc2010/openBIS+V3+API, I create a new sample of type SAMPLE_TYPE by

from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.create import SampleCreation
from ch.ethz.sis.openbis.generic.asapi.v3.dto.entitytype.id import EntityTypePermId

sample = SampleCreation()
sample.setTypeId(EntityTypePermId("SAMPLE_TYPE"))
sample.setParentIds([machine, identifier]) # identifier is the original sample 
sample.setProperty("$NAME", "Some Name")
...
created_sample = service.createSamples(sessionToken, [sample])

That fails since a sampleID is expected to be passed as 2nd argument.

java.lang.RuntimeException: java.lang.RuntimeException: class java.lang.String cannot be cast to class ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.IObjectId (java.lang.String is in module java.base of loader 'bootstrap'; ch.ethz.sis.openbis.generic.asapi.v3.dto.common.id.IObjectId is in unnamed module of loader org.eclipse.jetty.webapp.WebAppClassLoader @13d9cbf5) (Context: [])

Does the sample have a SamplePermId​ before it is created by “createSamples”?
Thanks for your help.

Regards,
Volker

Hi Volker

I would like to emphasize a very important aspect when programming dropboxes: all modification operations (creations, updates, file transfers) must use the V2 API and all read operations should preferably use the V3 (but this part is not a must). The reason is that the V3 search API is more efficient, however when the V3 API is used for modification operations, it is not invoked in the transactional context of the dropbox; this means that if one operation fails in the middle, the changes will not be rolled back, and you might end up with inconsistent data. For example, if you create multiple samples and one creation fails, the samples, which have been created, will remain in the system, but this behaviour is almost always undesirable.

This is a snipped from a Dropbox of another project. From it, you can get the idea of how to create samples:

from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.id import SampleIdentifier

def _get_or_create_sample(transaction, space_code, project_code, sample_code, sample_type_code, project, experiment, sample_name):
    sample_identifier = SampleIdentifier(space_code, project_code, None, sample_code).toString()
    found_sample = transaction.getSampleForUpdate(sample_identifier)
    if found_sample is None:
        sample = transaction.createNewSample(sample_identifier, sample_type_code)
        sample.setProject(project)
        sample.setExperiment(experiment)
        sample.setPropertyValue("$NAME", sample_name)

        return sample
    else:
        return found_sample

I hope this helps to clarify the sample creation process. If you are still experiencing issues, please let me know.

Cheers,
Viktor

Hi Viktor,

thanks for making explicitly the separation between the purposes of both APIs. I wasn’t aware of that. I understood an apparent movement to V3 and tried to use it wherever possible.

Cheers ,
Volker

1 Like

Thanks @viktor.kovtun for the explanation indeed. It would be great if the next Dropbox version would use the V3 API transactionally. It is generally a much cleaner API than the V2!