GPF.createProduct in jython


I try write wps on geoserver uses snappy. Geoserver uses jython so I have to rewrite the script.
My code:

import sys
import os
from java.lang import String
from geoserver.wps import process
from geoscript.geom import Geometry
from org.geotools.coverage.grid import GridCoverage2D

from org.esa.snap.core.gpf import GPF
from org.esa.snap.core.dataio import ProductIO
from java.util import HashMap
from org.esa.snap.core.gpf.common import MergeOp
from jarray import zeros

        'RedBand': (GridCoverage2D, 'Input red band'),
        'GreenBand': (GridCoverage2D, 'Input green band'),
        'BlueBand': (GridCoverage2D, 'Input blue band')},
    outputs={'result': (String, 'Result classification')}
def run(RedBand, GreenBand, BlueBand):
    red = ProductIO.readProduct('D:\\tmp\\T41VPD_20170603T065021_B04.jp2')
    green = ProductIO.readProduct('D:\\T41VPD_20170603T065021_B03.jp2')
    blue = ProductIO.readProduct('D:\\T41VPD_20170603T065021_B02.jp2')
    forest = 'D:\\forest_Polygon.shp'
    houses = 'D:\\houses_Polygon.shp'
    sourceProducts= HashMap()
    sourceProducts.put('masterProduct', red)
    sourceProducts.put('slaveProduct1', green)
    sourceProducts.put('slaveProduct2', blue)
    include_1 = MergeOp.NodeDescriptor()

    include_2 = MergeOp.NodeDescriptor()

    include_3 = MergeOp.NodeDescriptor()

    included_bands = zeros(3, include_2.getClass())

    included_bands[0] = include_1
    included_bands[1] = include_2
    included_bands[2] = include_3

    parameters = HashMap()
    parameters.put('includes', included_bands)

    mergedProduct = GPF.createProduct('Merge', parameters, sourceProducts)
    bands = mergedProduct.getBandNames()
    return str(mergedProduct.getName())

But i have error:

  File "..\scripts\wps\", line 64, in run
    mergedProduct = GPF.createProduct('Merge', parameters, sourceProducts)
        at org.esa.snap.core.gpf.internal.OperatorContext.processSourceProductField(
        at org.esa.snap.core.gpf.internal.OperatorContext.initSourceProductFields(
        at org.esa.snap.core.gpf.internal.OperatorContext.initSourceProductFields(
        at org.esa.snap.core.gpf.internal.OperatorContext.initializeOperator(
        at org.esa.snap.core.gpf.internal.OperatorContext.getTargetProduct(
        at org.esa.snap.core.gpf.Operator.getTargetProduct(
        at org.esa.snap.core.gpf.GPF.createProductNS(
        at org.esa.snap.core.gpf.GPF.createProduct(
        at org.esa.snap.core.gpf.GPF.createProduct(
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(
        at java.lang.reflect.Method.invoke(

org.esa.snap.core.gpf.OperatorException: org.esa.snap.core.gpf.OperatorException: Operator 'MergeOp': Mandatory source product (field 'masterProduct') not set.

What’s my mistake?


Actually the code looks good, but maybe the reason is the input path for the red product.
It’s D:\\tmp\\ the two others are directly at D:\\. Or there is something else wrong with the reading of the input.


Oh no! With the paths in the original everything is fine. This is a mistake in the reduction for the forum.
How can I check reading of the inputs?


After reading it you can check if it is null, or in python terms None.

Beside this, renaming the band in the master will not work. At least not with version 5.x.This will work with the upcoming release of version 6.
The merge operation in version 5 takes always the whole master product and only merges the other into it.
So to rename the master you could do the following:


You also need only two nodedescriptors for the two slave products.


Ok! I am reading product and when I try get name have a error.

 File "..\scripts\wps\", line 29, in run
    red = ProductIO.readProduct('D:\\tmp\\T41VPD_20170603T065021_B04.jp2')
        at javax.imageio.ImageIO.createImageInputStream(
        at org.esa.snap.dataio.bigtiff.BigGeoTiffProductReaderPlugIn.getDecodeQualification(
        at org.esa.snap.core.dataio.ProductIO.getProductReaderForInput(
        at org.esa.snap.core.dataio.ProductIO.readProductImpl(
        at org.esa.snap.core.dataio.ProductIO.readProduct(
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(
        at java.lang.reflect.Method.invoke(

java.lang.NoClassDefFoundError: java.lang.NoClassDefFoundError: it/geosolutions/imageio/stream/input/FileImageInputStreamExtImpl


In this case your class path is not complete.
You need also this jar imageio-ext-streams-1.2-SENTBX.
Maybe others might be missing too.


The Geoserver have self imageio-ext-* libraries.
I must rewrite they?


Maybe SNAP can’t find them. I guess the class paths are separate. And in addition ours contain some fixes which are not in the official ones.


Oh! I found warning “Provider org.esa.snap.python.gpf.PyOperatorSpi could not be instantiated”. Maybe my error is due to this.


In this case jpy.jar is missing. It is located in the snap\modules\ext\org.esa.snap.snap-python\org-jpy within the SNAP installation directory.