Troubleshooting and FAQs

Troubleshooting Issues

Packaging Issue

Problem Description: After packaging Java API with Maven, it throws NoClassDefFoundError: net/jpountz/lz4....

Cause: Maven packaging did not include third-party dependency jars.

Solution:

  1. Include the dependency jars manually when running the jar file:

    java -cp ".:./api-java-1.0.27-SNAPSHOT.jar:./lz4-java-1.7.1.jar" ...
  2. Use the Maven assembly plugin to package dependencies.

    Modify pom.xml:

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
            <appendAssemblyId>false</appendAssemblyId>
            <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <archive>
                <manifest>
                    <mainClass>com.xxdb.MTW_ParThread_Test.Main</mainClass>
                </manifest>
            </archive>
        </configuration>
        <executions>
            <execution>
                <id>make-assembly</id>
                <phase>package</phase>
                <goals>
                    <goal>assembly</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

    Package with Maven:

    mvn assembly:assembly clean install

Wrong Package

Error:
no instance of type variable exist so that BasicIntVector conforms to Vector inference...

Cause: Incorrect Vector interface import.

Solution: Import the correct Vector interface provided by the API.

Escaping Errors

Script:

sqlFormat = "select * from pt where date(%s) = %s,SecurityID like  '600%'";
conn.run(String.format(sqlFormat, arg));

Error:

java.util.UnknownFormatConversionException: Conversion = '''

Cause: In Java String.format, % is used as a placeholder, which conflicts with SQL like syntax.

Solution:

Escape % using %%:

sqlFormat = "select * from pt where date(%s) = %s, SecurityID like '600%%'";

Inconsistent Results with GUI

Problem Description:

Java API run function results differ from GUI results.

API Script:

conn.login("admin", "123456", false);
StringBuilder sb = new StringBuilder();
sb.append("'")
  .append("F:" + File.separator + "dolphinDB2" + File.separator + "DolphinDB_GUI_V1.30.13" + File.separator + "workspace" + File.separator + "test1" + File.separator + "scripts" + File.separator + "GenTradeTable.txt")
  .append("'");
Entity run = conn.run(sb.toString());
System.out.println("run.getString():" + run.getString());

DolphinDB GUI Script:

n=2000
syms=`YHOO`GE`MS`MSFT`JPM`ORCL`CISCO
timestamp=09:30:00+rand(18000, n)
sym=rand(syms, n)
qty=100*(1+rand(100,n))
price=5.0+rand(100.0, n)
t1=table(timestamp,sym,qty,price);
t1

Cause: Java API's run method expects a script as a string, differing from server run method.

Solution:

Run the file's script in the API's run method:

DBConnection conn = new DBConnection();
conn.connect("localhost",8848,"admin","123456");
StringBuilder sb = new StringBuilder();
String script = "run(\"D:/work/GenTradeTable.txt\")";
System.out.println(script);
BasicTable res = (BasicTable) conn.run(script);
System.out.println("run.getString():"+res.getString());

FAQs

Q: How to construct a Dictionary using Java API?

A: To construct a dictionary directly in DolphinDB using the Java API, you can instantiate a BasicDictionary by specifying the key and value types (e.g., key is DT_INT, value is DT_STRING). Then, you can use the put method to insert key-value pairs. For example:

BasicDictionary dictionary = new BasicDictionary(Entity.DATA_TYPE.DT_INT, Entity.DATA_TYPE.DT_STRING);
dictionary.put(new BasicInt(1),new BasicString("IBM"));
System.out.println(dictionary.getString());

Q: How to get the column names and types of a table when only the table name is known?

A: If you only know the table name, you can use the loadTable function to get the table first and then use the columnNames function to retrieve the column names. For example:

List<Entity> arguments1 = new ArrayList<Entity>(1); 
BasicTable table1 = (BasicTable) conn.run("loadTable('dfs://testDatabase','pt')"); 
arguments1.add(table1); 
BasicStringVector o1 = (BasicStringVector)conn.run("columnNames",arguments1); 
System.out.println(o1.getString());

Q: How to convert temporal values to integers when constructing BasicDateVector / BasicTimeVector in Java API?

A: You can convert dates or times to integers using the following methods:

DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HHmmssSSS");
Utils.countDays(LocalDate.parse(currentDate, dateFormatter))
Utils.countMilliseconds(LocalTime.parse(String.format("%09d", Integer.parseInt(localCurrentTime)), timeFormatter))

Q: How to get the number of successfully inserted records after calling tableInsert in Java API?

A: When you execute tableInsert using the Java API, the return value entity is of type BasicInt. You can directly print entity to see the number of successfully inserted records. For example:

Entity entity = conn.run("tableInsert(...)");
System.out.println(((BasicInt) entity).getInt());  

Q: Handling EOFException after subscribing to a stream table

Successfully reconnected and subscribed xxxx:8903/DemoStreamjavaStreamingApi
java.io.EOFException
at com.xxdb.io.AbstractExtendedDataInputStream.readUnsignedByte(AbstractExtendedDataInputStream.java:116)
at com.xxdb.io.AbstractExtendedDataInputStream.readBoolean(AbstractExtendedDataInputStream.java:21)
at com.xxdb.streaming.client.MessageParser.run(MessageParser.java:68)
at java.lang.Thread.run(Thread.java:748)

A: The EOFException may occur if multiple threads are sharing a session, leading to buffer serialization failure.

Q: How to convert BasicTable with array vector types to a format accepted by MultiThreadedTableWriter::insert?

A: Convert columns to BasicArrayVector and then to Entity[]:

for (int rowIdx = 0; rowIdx < data.rows(); rowIdx++) {
    List<Object> row = new ArrayList<>();
    for (int k = 0; k < data.columns(); k++) {
        Vector col = data.getColumn(k);
        if (col instanceof BasicArrayVector) {
            Vector vecVal = ((BasicArrayVector) col).getVectorValue(rowIdx);
            Entity[] vecValRes = new Entity[vecVal.rows()];
            for (int vecValidx = 0; vecValidx < vecVal.rows(); vecValidx++) {
                vecValRes[vecValidx] = vecVal.get(vecValidx);
            }
            row.add(vecValRes);
        } else {
            row.add(col.get(rowIdx));
        }
    }
    mtwWriter.insert(row.toArray());
}