Dukascopy Support Board
http://www.dukascopy.com/swiss/english/forex/jforex/forum/

NullPointerException on initialised Client instance
http://www.dukascopy.com/swiss/english/forex/jforex/forum/viewtopic.php?f=16&t=57751
Page 1 of 1

Author:  degeorge [ Mon 06 Dec, 2021, 17:51 ]
Post subject:  NullPointerException on initialised Client instance

Hi, i'am thinking this is the bug or some kind of unexpected behaviour.
JForex version: 3.6.39
JForex API version: 2.13.98

Reproducing:
1. Save this code as jforex terminal plugin with file name as TestPlugin.java:
package jforex;

import com.dukascopy.api.*;
import com.dukascopy.api.plugins.IPluginContext;
import com.dukascopy.api.plugins.Plugin;
import com.dukascopy.api.system.ClientFactory;
import com.dukascopy.api.system.IClient;
import com.dukascopy.api.system.IStrategyExceptionHandler;

@RequiresFullAccess // don't know is this needed here
public class TestPlugin extends Plugin {

    @Override
    public void onStart(IPluginContext context) throws JFException {
        try {
            final IClient client = ClientFactory.getDefaultInstance();
            if (client == null) {
                context.getConsole().getErr().println("null client instance");
            } else {
                final DeadSimpleStrategy strategy = new DeadSimpleStrategy();
                context.getConsole().getOut().println(client);
                client.startStrategy(strategy, strategy);
            }
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            context.getConsole().getErr().println(e.getLocalizedMessage());
        }
    }

    @Override
    public void onStop() throws JFException {
        super.onStop();
    }
   
    public static class DeadSimpleStrategy implements IStrategy, IStrategyExceptionHandler {

        @JFXInject
        IContext ctx;
        @JFXInject
        IConsole console;

        @Override
        public void onStart(IContext context) throws JFException {
            console.getOut().println("Strategy started");
        }

        @Override
        public void onTick(Instrument instrument, ITick tick) throws JFException {

        }

        @Override
        public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {

        }

        @Override
        public void onMessage(IMessage message) throws JFException {

        }

        @Override
        public void onAccount(IAccount account) throws JFException {

        }

        @Override
        public void onStop() throws JFException {
            console.getOut().println("Strategy stopped!");
        }

        @Override
        public void onException(long strategyId, Source source, Throwable t) {
            console.getErr().printf("Strategy: %d Error: %s%n", strategyId, t.toString());
            this.ctx.stop();
        }
    }
}

2. Compile plugin.
3. Activate plugin.
4. Open forex terminal error log and find something like this:
java.lang.NullPointerException @ com.dukascopy.api.impl.connect.DCClientImpl.a(L:1248)

null: java.lang.NullPointerException
   at com.dukascopy.api.impl.connect.DCClientImpl.a(L:1248)
   at com.dukascopy.api.impl.connect.DCClientImpl.startStrategy(L:1226)
   at jforex.TestPlugin.onStart(TestPlugin.java:22)
   at com.dukascopy.api.plugins.Plugin.onStart(Plugin.java:9)
   at com.dukascopy.api.impl.execution.s.call(L:30)
   at com.dukascopy.api.impl.execution.s.call(L:15)
   at com.dukascopy.api.impl.connect.at.a(L:140)
   at com.dukascopy.api.impl.connect.JForexTaskManager.a(L:887)
   at com.dukascopy.api.impl.execution.j.call(L:34)
   at java.util.concurrent.FutureTask.run(FutureTask.java:266)
   at com.dukascopy.api.impl.execution.f$a.e(L:904)
   at com.dukascopy.api.impl.execution.f$a.run(L:926)
   at java.lang.Thread.run(Thread.java:748)


Expected:
No NullPointerException

Explanation:
I assume I wrote correct code from java and forex api perspective.
Inside the plugin onStart method i'am trying to create instance of IClient class on line 16, because of its singleton nature, I assume that I will get same instance that is auto create when i'am log in into the terminal application. Checking null condition successfully print to the console IClient instance (line 21), but executing startStrategy method (line 22) resulting in NullPointerException in error log. I also tried with DeadSimpleStrategy implementation from separate file (not as nested class) - same behaviour.
If I change IClient to ITesterClient (line 16 + appropriate import):
final ITesterClient client = TesterFactory.getDefaultInstance();

- everything is fine, but of course strategy will not started because client not connected (Connection error).

So, in my opinion this is incorrect behaviour, if usage of IClient inside plugin or maybe totally inside terminal app - is not supported it would be better if it would be more transparent or explicit to the client, for example: ClientFactory.getDefaultInstance() call could return InstantiationException when in terminal context - this is bad, I understand, i'am not experienced in jforex sdk internals, but just as idea. Also improved java docs maybe enough, just expose some restrictions of IClient interface in docs.

Offtopic:
Conceptually, I'am trying to create plugin that continuously working as server (zmq, http, grpc or whatever, doesn't matter) and spawn new strategies per client (or several per client, could be complex logic). I'am trying started new strategies via IClient and ITesterClient instances (not via IStrategyManager) because I want to eliminate needs to compile strategy in runtime or precompiled on artifact (jar) building stage. Is i'am on the right way or maybe somebody could help me to get better direction?

Thanks.

Author:  API Support [ Mon 13 Dec, 2021, 14:10 ]
Post subject:  Re: NullPointerException on initialised Client instance

Greetings.

NPE will be fixed in next platform release.
java.lang.IllegalStateException: Not connected
will be thrown instead.

Client has to make connection before starting the strategy.

Regards.

Author:  degeorge [ Mon 13 Dec, 2021, 14:37 ]
Post subject:  Re: NullPointerException on initialised Client instance

Thanks for reply!
Could you clarify this: "Client has to make connection before starting the strategy." - you mean that in my code I need add client.connect() call (with appropriate code for handling state via ISystemListener) after instantiation of IClient instance inside of my plugin code? Is this means that platform (terminal app runtime) has its own "connection" and didn't share it with IClient that I acquire myself? This is coming to my mind from the assumption that IClient encapsulates some "connection" itself, so if IClient is singleton -> "connection" is shared via IClient instance, that's why I think that creating IClient inside terminal app runtime already provides me connection in connected state...

Author:  vadim_berezhnoj [ Thu 06 Jan, 2022, 14:37 ]
Post subject:  Re: NullPointerException on initialised Client instance

IClient is designed for using from SDK - it is not used inside JForex platform, therefore it can't share connection with platform.

Regards.

  Page 1 of 1