Options

Execute Script vs Java Extension coding

sgenzersgenzer Administrator, Moderator, Employee, RapidMiner Certified Analyst, Community Manager, Member, University Professor, PM Moderator Posts: 2,959 Community Manager
edited November 2019 in Help

OK I think I am just a glutton for punishment but I keep trying to create a simple extension that executes API GET requests.  I thought I had it clinched this weekend using the nice "unirest" library.  In fact it works perfectly when using the Execute Script operator:

 

<?xml version="1.0" encoding="UTF-8"?><process version="7.6.001">
<context>
<input/>
<output/>
<macros/>
</context>
<operator activated="true" class="process" compatibility="7.6.001" expanded="true" name="Process">
<process expanded="true">
<operator activated="true" class="generate_data_user_specification" compatibility="7.6.001" expanded="true" height="68" name="Generate Data by User Specification" width="90" x="179" y="187">
<list key="attribute_values"/>
<list key="set_additional_roles"/>
</operator>
<operator activated="true" class="execute_script" compatibility="7.6.001" expanded="true" height="82" name="Execute Script" width="90" x="313" y="187">
<parameter key="script" value="import com.mashape.unirest.http.*;&#10;import com.mashape.unirest.http.exceptions.UnirestException;&#10;import com.rapidminer.tools.Ontology;&#10;&#10;IOObject inputData = input[0];&#10;&#10;Attributes attributes = inputData.getAttributes();&#10;&#10;Attribute jsonOutput = AttributeFactory.createAttribute(&quot;jsonOutput&quot;, Ontology.STRING);&#10;&#10;attributes.addRegular(jsonOutput);&#10;&#10;inputData.getExampleTable().addAttribute(jsonOutput);&#10;&#10;for (Example example : inputData) {&#10;&#9;&#10;&#9;HttpResponse&lt;JsonNode&gt; response = Unirest.get(&quot;https://community-bitcointy.p.mashape.com/convert/10/USD&quot;)&#10;&#9;&#9;.header(&quot;X-Mashape-Key&quot;, &quot;izQxTY0KZ4mshmrBq7DmXQvlC3hcp16709BjsngW8gm71mH39j&quot;)&#10;&#9;&#9;.header(&quot;X-Mashape-Host&quot;, &quot;community-bitcointy.p.mashape.com&quot;)&#10;&#9;&#9;.asJson();&#10;&#9;JsonNode foo = response.getBody();&#9;&#10;&#9;String jsonText = foo.toString();&#10;&#9;example.setValue(jsonOutput, jsonText);&#10;}&#10;&#10;return inputData;&#10;"/>
<description align="center" color="transparent" colored="false" width="126">this works</description>
</operator>
<connect from_op="Generate Data by User Specification" from_port="output" to_op="Execute Script" to_port="input 1"/>
<connect from_op="Execute Script" from_port="output 1" to_port="result 1"/>
<portSpacing port="source_input 1" spacing="0"/>
<portSpacing port="sink_result 1" spacing="0"/>
<portSpacing port="sink_result 2" spacing="0"/>
</process>
</operator>
</process>

However when I try to put this in the "extension template", I can never get this to compile:

 

package com.rapidminer.apitoolbox;

import java.util.logging.Level;
import com.rapidminer.example.Attribute;
import com.rapidminer.example.Attributes;
import com.rapidminer.example.Example;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.example.table.AttributeFactory;
import com.rapidminer.example.utils.ExampleSetBuilder;
import com.rapidminer.example.utils.ExampleSets;
import com.rapidminer.operator.Operator;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.ports.InputPort;
import com.rapidminer.operator.ports.OutputPort;
import com.rapidminer.operator.ports.metadata.AttributeMetaData;
import com.rapidminer.operator.ports.metadata.ExampleSetMetaData;
import com.rapidminer.operator.ports.metadata.GenerateNewExampleSetMDRule;
import com.rapidminer.operator.ports.metadata.MetaData;
import com.rapidminer.parameter.ParameterType;
import com.rapidminer.parameter.ParameterTypeBoolean;
import com.rapidminer.parameter.ParameterTypeInt;
import com.rapidminer.parameter.UndefinedParameterError;
import com.rapidminer.tools.LogService;
import com.mashape.unirest.http.*;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.rapidminer.tools.Ontology;

/**
* This operator calls the Bitcointy API (via RapidAPI/Mashape)
* and gets the current USD/BTC exchange rate.
*
* @author S. Genzer on 1 Oct 2017
*
*/

public class bitcoin extends Operator {

/**
* @param description
*/

public InputPort exampleSetInput = getInputPorts()
.createPort("exa");
public OutputPort exampleSetOutput = getOutputPorts()
.createPort("exa");

public bitcoin(OperatorDescription description) {
super(description);
}

@Override

public void doWork() throws OperatorException {
LogService.getRoot().log(Level.INFO, "Doing something...");

ExampleSet exampleSet = exampleSetInput.getData(ExampleSet.class);

Attributes attributes = exampleSet.getAttributes();

Attribute jsonOutput = AttributeFactory.createAttribute("jsonOutput", Ontology.STRING);

attributes.addRegular(jsonOutput);

exampleSet.getExampleTable().addAttribute(jsonOutput);

for (Example example : exampleSet) {

HttpResponse<JsonNode> response = Unirest.get("https://community-bitcointy.p.mashape.com/convert/10/USD")
.header("X-Mashape-Key", "key")
.header("X-Mashape-Host", "community-bitcointy.p.mashape.com")
.asJson();
JsonNode foo = response.getBody();
String jsonText = foo.toString();
example.setValue(jsonOutput, jsonText);
}

exampleSetOutput.deliver(exampleSet);

}
}

Help?  This is maddening.

 

Scott

 

Best Answer

  • Options
    MartinLiebigMartinLiebig Administrator, Moderator, Employee, RapidMiner Certified Analyst, RapidMiner Certified Expert, University Professor Posts: 3,507 RM Data Scientist
    Solution Accepted

    Scott,

     

    i've added the class to a branch of operatortoolbox. A few things:

     

    1. Have you added

    compile 'com.mashape.unirest:unirest-java:1.3.1'

    to your gradle dependencies?

    2.

    response = Unirest.get("https://community-bitcointy.p.mashape.com/convert/10/USD") ...

    needs a try catch.

    3. you added two different implementations of JsonNode. One from mashable the other from

    com.fasterxml.jackson.databind.

    that screwed it up.

     

    Here the code i was able to compile (but not tested the operator though):

     

    //package com.rapidminer.apitoolbox;
    package com.rapidminer.extension.operator.blending;
    //import com.fasterxml.jackson.databind.JsonNode;
    import com.mashape.unirest.http.*;
    import com.mashape.unirest.http.exceptions.UnirestException;
    import com.rapidminer.example.Attribute;
    import com.rapidminer.example.Attributes;
    import com.rapidminer.example.Example;
    import com.rapidminer.example.ExampleSet;
    import com.rapidminer.example.table.AttributeFactory;
    import com.rapidminer.operator.Operator;
    import com.rapidminer.operator.OperatorDescription;
    import com.rapidminer.operator.OperatorException;
    import com.rapidminer.operator.ports.InputPort;
    import com.rapidminer.operator.ports.OutputPort;
    import com.rapidminer.tools.LogService;
    import com.rapidminer.tools.Ontology;

    import java.util.logging.Level;

    /**
    * This operator calls the Bitcointy API (via RapidAPI/Mashape)
    * and gets the current USD/BTC exchange rate.
    *
    * @author S. Genzer on 1 Oct 2017
    *
    */

    public class BitCoin extends Operator {

    /**
    * @param description
    */

    public InputPort exampleSetInput = getInputPorts()
    .createPort("exa");
    public OutputPort exampleSetOutput = getOutputPorts()
    .createPort("exa");

    public BitCoin(OperatorDescription description) {
    super(description);
    }

    @Override

    public void doWork() throws OperatorException {
    LogService.getRoot().log(Level.INFO, "Doing something...");

    ExampleSet exampleSet = exampleSetInput.getData(ExampleSet.class);

    Attributes attributes = exampleSet.getAttributes();

    Attribute jsonOutput = AttributeFactory.createAttribute("jsonOutput", Ontology.STRING);

    attributes.addRegular(jsonOutput);

    exampleSet.getExampleTable().addAttribute(jsonOutput);

    for (Example example : exampleSet) {

    HttpResponse<com.mashape.unirest.http.JsonNode> response = null;
    try {
    response = Unirest.get("https://community-bitcointy.p.mashape.com/convert/10/USD")
    .header("X-Mashape-Key", "key")
    .header("X-Mashape-Host", "community-bitcointy.p.mashape.com")
    .asJson();
    } catch (UnirestException e) {
    e.printStackTrace();
    }
    JsonNode foo = response.getBody();
    String jsonText = foo.toString();
    example.setValue(jsonOutput, jsonText);
    }

    exampleSetOutput.deliver(exampleSet);

    }
    }
    - Sr. Director Data Solutions, Altair RapidMiner -
    Dortmund, Germany

Answers

  • Options
    sgenzersgenzer Administrator, Moderator, Employee, RapidMiner Certified Analyst, Community Manager, Member, University Professor, PM Moderator Posts: 2,959 Community Manager

    @mschmitz, a.k.a. "the man with the cape" comes through again.  Thank you.  I knew it was some conflict with that JsonNode call but could not find it.  Yes I had put the compile statement in the dependencies in build.gradle.  Not bad for an EE major, right?  :)


    Scott

     

Sign In or Register to comment.