Welcome! Please see the About page for a little more info on how this works.

0 votes
in Java Interop by

Hi everyone,

Failing to make clojure work with our commercial java library. I can run the following Java code on my machine and it works fine:

import com.numerix.pro.Application;
import com.numerix.pro.ApplicationCall;
import com.numerix.pro.ApplicationData;
import com.numerix.pro.ApplicationObjectFactory;
import com.numerix.pro.ApplicationWarning;

public final class FxAmericanOption {

    public static void main(final String argv[]) 
    {
        int rVal = 0;      // exit value
        try {
            System.out.println("Running: " + new Throwable().getStackTrace()[0].getClassName() + "\n");

            final Application app = new Application();
            {
                final ApplicationCall call = new ApplicationCall();
                call.addValue("ID",       "USD_Curve");
                call.addValue("OBJECT",   "Curve");
                call.addValue("TYPE",     "Yield");
                call.addValue("Now Date", ApplicationObjectFactory.parseDate("26-Oct-2003"));
                call.addValue("CURRENCY", "USD");
                call.addValue("RATE",     0.04);

                final String[] outHeaders =
                    new String[] {"Updated", "Timer", "ID"};

                final ApplicationWarning warning = new ApplicationWarning();

                app.call(call, outHeaders, warning);

I tried porting it to clojure 1.12 like this

(ns hello
  (:import (com.numerix.pro Application ApplicationCall
                            ApplicationWarning 
                            ApplicationObjectFactory)))
           
(def myapp (new Application))
(def appcall (new ApplicationCall))
(def warning (new ApplicationWarning))

(.addValue ^ApplicationCall appcall "NAME" "Yield Curve")
(.addValue ^ApplicationCall appcall "ID" "MyCurve")
(.addValue ^ApplicationCall appcall "OBJECT" "Curve")
(.addValue ^ApplicationCall appcall "TYPE" "Yield")
(.addValue ^ApplicationCall appcall "Now Date" (ApplicationObjectFactory/parseDate "26-Oct-2023"))
(.addValue ^ApplicationCall appcall "CURRENCY" "USD")
(.addValue ^ApplicationCall appcall "RATE" 0.04)

(def outHeaders (into-array String ["timer" "id"]))

(^[ApplicationCall String/1 ApplicationWarning] Application/.call ^Application myapp
                                                                  ^ApplicationCall appcall
                                                                  ^String/1 outHeaders
                                                                  ^ApplicationWarning warning)

I can inspect appcall object and it looks totally fine - all the .addValue register correctly with it. But when I evaluate the last form with Application/.call I get an error which I don't understand how to address..

 Execution error (IllegalAccessError) at hello/eval10370 (REPL:25).
; failed to access class com.numerix.pro.ApplicationCommon from class hello$eval10370 (com.numerix.pro.ApplicationCommon is in unnamed module of loader 'app'; hello$eval10370 is in unnamed module of loader clojure.lang.DynamicClassLoader @cc01572)

Any help much appreciated!

1 Answer

0 votes
by

Can you do (pst *e) and provide that too? It's complaining about ApplicationCommon class which does not seem accessible from Clojure's classloader. That class doesn't show up in your code so I'm not sure how/why it's needed but might be something classloader related.

by
Thank you for looking into it Alex! Here's the result of (pst *e):
IllegalAccessError failed to access class com.numerix.pro.ApplicationCommon from class hello$eval10376 (com.numerix.pro.ApplicationCommon is in unnamed module of loader 'app'; hello$eval10376 is in unnamed module of loader clojure.lang.DynamicClassLoader @44292697)
;
;     hello/eval10376 (NO_SOURCE_FILE:25)
;
;     hello/eval10376 (NO_SOURCE_FILE:25)
;
;     clojure.lang.Compiler.eval (Compiler.java:7700)
;
;     clojure.lang.Compiler.eval (Compiler.java:7655)
;
;     clojure.core/eval (core.clj:3232)
;
;     clojure.core/eval (core.clj:3228)
;
;     nrepl.middleware.interruptible-eval/evaluate/fn--1357/fn--1358 (interruptible_eval.clj:87)
;
;     clojure.core/apply (core.clj:667)
;
;     clojure.core/with-bindings* (core.clj:1990)
;
;     clojure.core/with-bindings* (core.clj:1990)
;
;     nrepl.middleware.interruptible-eval/evaluate/fn--1357 (interruptible_eval.clj:87)
;
;     clojure.main/repl/read-eval-print--9244/fn--9247 (main.clj:437)
by
The error "IllegalAccessError failed to access class com.numerix.pro.ApplicationCommon from class hello$eval10376" indicates that there is some kind of accessibility problem using or calling ApplicationCommon - probably a private class rather than a module visibility issue I would guess since it's in an unnamed module. Not knowing the underlying app, it's hard to tell what's wrong. Can you shed any light on what ApplicationCommon is and it relates to the code you posted?
...