rzeznik
rzeznik

Reputation: 91

Hive UDF - Java String castexception

I have written UDF that decodes cookie and returns List of strings. Unfortunately i got Hive Runtime error while processing

here is my code:

@Override
public ObjectInspector initialize(ObjectInspector[] input) throws UDFArgumentException {

    ObjectInspector cookieContent = input[0];
    if (!(isStringOI(cookieContent))){
        throw new UDFArgumentException("only string");
    }
    this.cookieValue = (StringObjectInspector) cookieContent;
    return ObjectInspectorFactory.getStandardListObjectInspector
            (PrimitiveObjectInspectorFactory.javaStringObjectInspector);
}


public Object evaluate(DeferredObject[] input) throws HiveException {

    String encoded = cookieValue.getPrimitiveJavaObject(input[0].get());
    try {
        result = decode(encoded);
    } catch (CodeException e) {
        throw new UDFArgumentException();
    }

    return result;
}
public List<String> decode(String encoded) throws CodeException {

    decodedBase64 = Base64.decodeBase64(encoded);
    String decompressedArray = new String(getKadrs(decodedBase64));
    String kadr= decompressedArray.substring(decompressedArray.indexOf("|") + 1);
    List<String> kadrsList= new ArrayList(Arrays.asList(kadr.split(",")));
    return kadrsList;
}

private byte[] getKadrs(byte[] compressed) throws CodeException {
    Inflater decompressor = new Inflater();
    decompressor.setInput(compressed);
    ByteArrayOutputStream outPutStream = new ByteArrayOutputStream(compressed.length);
    byte temp [] = new byte[1024];
    while (!decompressor.finished()) {
        try {
            int count = decompressor.inflate(temp);
            outPutStream.write(temp, 0, count);
        }
        catch (DataFormatException e) {
            throw new CodeException ("Wrong data format", e);
        }
    }
    try {
        outPutStream.close();
    } catch (IOException e) {
        throw new CodeException ("Cant close outPutStream ", e);
    }
    return outPutStream.toByteArray();
}

Result of it is, lets say:

"kadr1, kadr20, kadr35, kadr12". Unit tests work fine but when i am trying to use this function in hive i got this:

   Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.hadoop.io.Text
  at org.apache.hadoop.hive.serde2.objectinspector.primitive.WritableStringObjectInspector.getPrimitiveWritableObject(WritableStringObjectInspector.java:41)

Its hard for me to debug cause other person must implement my jar to see results, so all advices will be appreciated.

Upvotes: 1

Views: 3921

Answers (2)

rzeznik
rzeznik

Reputation: 91

ravindra was right

i had in initialize
return ObjectInspectorFactory.getStandardListObjectInspector (PrimitiveObjectInspectorFactory.writableStringObjectInspector);

and WritableStringObjectInspector returns Text

i changed it to javaStringObjectInspector, which returns String and all is fine thanks

Upvotes: 1

OneCricketeer
OneCricketeer

Reputation: 191681

Your evaluate method currently returns a String, which is not a Hadoop datatype. You should instead wrap your string in a Text object by saying return new Text(result).

Upvotes: 1

Related Questions