Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tradeoff-analytics] Call to dilemmas() failing in Google stack #306

Closed
jeffpk62 opened this issue May 31, 2016 · 3 comments
Closed

[tradeoff-analytics] Call to dilemmas() failing in Google stack #306

jeffpk62 opened this issue May 31, 2016 · 3 comments
Assignees
Labels

Comments

@jeffpk62
Copy link
Contributor

jeffpk62 commented May 31, 2016

The following simple Tradeoff Analytics Java program (renamed for attachment)TradeoffAnalyticsExample.txt appears to be valid. But it elicits a JsonParseException:

Exception in thread "main" com.google.gson.JsonParseException: The JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@e6fb1de0 failed to deserialize json object [{"type":"numeric","key":"price","full_name":"Price","format":"number:2","goal":"min","is_objective":true},{"type":"numeric","key":"weight","full_name":"Weight","format":"number:0","goal":"min","is_objective":true},{"type":"categorical","key":"brand","full_name":"Brand","goal":"min","is_objective":true},{"type":"datetime","key":"rDate","full_name":"Release Date","format":"date: 'MMM dd, yyyy'","goal":"max","is_objective":false}] given the type java.util.List<com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.Column>
        at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:64)
        at com.google.gson.JsonDeserializationVisitor.invokeCustomDeserializer(JsonDeserializationVisitor.java:92)
        at com.google.gson.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler(JsonObjectDeserializationVisitor.java:117)
        at com.google.gson.ReflectingFieldNavigator.visitFieldsReflectively(ReflectingFieldNavigator.java:63)
        at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:120)
        at com.google.gson.JsonDeserializationVisitor.visitChild(JsonDeserializationVisitor.java:110)
        at com.google.gson.JsonDeserializationVisitor.visitChildAsObject(JsonDeserializationVisitor.java:99)
        at com.google.gson.JsonObjectDeserializationVisitor.visitObjectField(JsonObjectDeserializationVisitor.java:63)
        at com.google.gson.ReflectingFieldNavigator.visitFieldsReflectively(ReflectingFieldNavigator.java:69)
        at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:120)
        at com.google.gson.JsonDeserializationContextDefault.fromJsonObject(JsonDeserializationContextDefault.java:76)
        at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:54)
        at com.google.gson.Gson.fromJson(Gson.java:551)
        at com.google.gson.Gson.fromJson(Gson.java:498)
        at com.ibm.watson.developer_cloud.util.ResponseUtils.getObject(ResponseUtils.java:105)
        at com.ibm.watson.developer_cloud.service.WatsonService.executeRequest(WatsonService.java:184)
        at com.ibm.watson.developer_cloud.tradeoff_analytics.v1.TradeoffAnalytics.dilemmas(TradeoffAnalytics.java:96)
        at com.ibm.watson.developer_cloud.tradeoff_analytics.v1.TradeoffAnalyticsExample.main(TradeoffAnalyticsExample.java:119)
Caused by: java.lang.RuntimeException: Unable to invoke no-args constructor for class com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.Column. Register an InstanceCreator with Gson for this type may fix this problem.
        at com.google.gson.MappedObjectConstructor.constructWithAllocators(MappedObjectConstructor.java:68)
        at com.google.gson.MappedObjectConstructor.construct(MappedObjectConstructor.java:52)
        at com.google.gson.JsonObjectDeserializationVisitor.constructTarget(JsonObjectDeserializationVisitor.java:42)
        at com.google.gson.JsonDeserializationVisitor.getTarget(JsonDeserializationVisitor.java:60)
        at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:104)
        at com.google.gson.JsonDeserializationContextDefault.fromJsonObject(JsonDeserializationContextDefault.java:76)
        at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:54)
        at com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter.deserialize(DefaultTypeAdapters.java:663)
        at com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter.deserialize(DefaultTypeAdapters.java:624)
        at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:51)
        ... 17 more
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:95)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:56)
        at java.lang.reflect.Method.invoke(Method.java:620)
        at com.google.gson.UnsafeAllocator$1.newInstance(UnsafeAllocator.java:48)
        at com.google.gson.MappedObjectConstructor.constructWithAllocators(MappedObjectConstructor.java:64)
        ... 26 more
Caused by: java.lang.InstantiationError: com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.Column
        at sun.misc.Unsafe.allocateInstance(Native Method)
        ... 32 more

The JSON object that is failing appears to be valid. German's initial diagnosis was

The error is probably the service response. The TA team may have changed the response and that breaks the Java SDK because it can't transform the JSON into a POJO. The problem is on my side. I will probably switch the date column to be String instead of trying to parse it.

I also mentioned the following, probably gratuitous, points in email, which I include here just for the sake of completeness.:

German, I failed to mention this on yesterday's call, but the format field is really just a passthru to the widget. The service itself doesn't use or interpret the field at all; it just sends it as-is to the widget. The same is true for the full_name and description fields of columns and for the name, description_html, and app_data fields of options. So you can probably just ignore whatever is in these fields entirely as long as they're defined as valid JSON strings or, for app_data, as key/value pairs.

Testing with java-sdk-2.10.0-jar-with-dependencies.jar.

@germanattanasio
Copy link
Contributor

package com.ibm.watson.developer_cloud.tradeoff_analytics.v1;

import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.Dilemma;
import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.Option;
import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.Problem;
import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.Column;
import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.Column.Goal;
import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.NumericColumn;
import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.CategoricalColumn;
import com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.DateColumn;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class TradeoffAnalyticsExample {

  public static void main(String[] args) {

    TradeoffAnalytics service = new TradeoffAnalytics();
    service.setUsernameAndPassword("username",
                                   "password");

    // Define the objectives.
    String price = "price";
    String weight = "weight";
    String brand = "brand";
    String rDate = "rDate";

    List<String> categories = new ArrayList<String>();
    categories.add("Apple");
    categories.add("HTC");
    categories.add("Samsung");

    List<String> preferences = new ArrayList<String>();
    preferences.add("Samsung");
    preferences.add("Apple");
    preferences.add("HTC");

    NumericColumn priceColumn = new NumericColumn();
    priceColumn.withKey(price);
    priceColumn.withGoal(Goal.MIN);
    priceColumn.withObjective(true);
    priceColumn.withFullName("Price");
    priceColumn.withRange(0, 400);
    priceColumn.setFormat("number:2");

    NumericColumn weightColumn = new NumericColumn();
    weightColumn.withKey(weight);
    weightColumn.withGoal(Goal.MIN);
    weightColumn.withObjective(true);
    weightColumn.withFullName("Weight");
    weightColumn.setFormat("number:0");

    CategoricalColumn brandColumn = new CategoricalColumn();
    brandColumn.withKey(brand);
    brandColumn.withGoal(Goal.MIN);
    brandColumn.withObjective(true);
    brandColumn.withFullName("Brand");
    brandColumn.setRange(categories);
    brandColumn.setPreference(preferences);

    DateColumn rDateColumn = new DateColumn();
    rDateColumn.withKey(rDate);
    rDateColumn.withGoal(Goal.MAX);
    rDateColumn.withFullName("Release Date");
    rDateColumn.setFormat("date: 'MMM dd, yyyy'");

    List<Column> columns = new ArrayList<Column>();
    columns.add(priceColumn);
    columns.add(weightColumn);
    columns.add(brandColumn);
    columns.add(rDateColumn);

    Problem problem = new Problem("phones");
    problem.setColumns(columns);

    /*
    columns.add(new NumericColumn().withKey(price).withGoal(Goal.MIN)
                .withObjective(true).withFullName("Price").withRange(0, 400)
                .withFormat("number:2"));
    columns.add(new NumericColumn().withKey(weight).withGoal(Goal.MIN)
                .withObjective(true).withFullName("Weight")
                .withFormat("number:0"));
    columns.add(new CategoricalColumn().withKey(brand).withGoal(Goal.MIN)
                .withObjective(true).withFullName("Brand")
                .withRange(categories)
                .withPreference("Samsung", "Apple", "HTC"));
    columns.add(new DateColumn().withKey(rDate).withGoal(Goal.MAX)
                .withFullName("Release Date")
                .withFormat("date: 'MMM dd, yyyy'"));
    */

    // Define the options.
    List<Option> options = new ArrayList<Option>();
    problem.setOptions(options);

    HashMap<String, Object> galaxySpecs = new HashMap<String, Object>();
    galaxySpecs.put(price, 249);
    galaxySpecs.put(weight, 130);
    galaxySpecs.put(brand, "Samsung");
    galaxySpecs.put(rDate, "2013-04-29T00:00:00Z");
    options.add(new Option("1", "Samsung Galaxy S4").withValues(galaxySpecs));

    HashMap<String, Object> iphoneSpecs = new HashMap<String, Object>();
    iphoneSpecs.put(price, 449);
    iphoneSpecs.put(weight, 112);
    iphoneSpecs.put(brand, "Apple");
    iphoneSpecs.put(rDate, "2012-09-21T00:00:00Z");
    options.add(new Option("2", "Apple iPhone 5").withValues(iphoneSpecs));

    HashMap<String, Object> oneSpecs = new HashMap<String, Object>();
    oneSpecs.put(price, 299);
    oneSpecs.put(weight, 143);
    oneSpecs.put(brand, "HTC");
    oneSpecs.put(rDate, "2013-03-01T00:00:00Z");
    options.add(new Option("3", "HTC One").withValues(oneSpecs));

    // Call the service and get the resolution
    Dilemma dilemma = service.dilemmas(problem, false);
    System.out.println(dilemma);

  }
}

@germanattanasio
Copy link
Contributor

This is a problem that was fixed in v3.0.0. The problem is that ResponseUtils was not using GsonSingleton to serialize the Problem.java object to a JSON request.
I'm marking this as won't fix since we won't work on v2.X anymore but it's good to have a registry about the issue here

@shekhargowda
Copy link

shekhargowda commented Mar 14, 2017

@germanattanasio

This issue is occurring with 3.6.0 also.

Unable to invoke no-args constructor for class com.ibm.watson.developer_cloud.tradeoff_analytics.v1.model.column.Column. Register an InstanceCreator with Gson for this type may fix this problem.

               <dependency>
		<groupId>com.ibm.watson.developer_cloud</groupId>
		<artifactId>tradeoff-analytics</artifactId>
		<version>3.6.0</version>
	</dependency>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

5 participants