2016-10-25 2 views
3

Я пытаюсь запустить код Python на сервере Coldfusion с использованием Java. Я знаком с CFML, но абсолютным новичком с Java.Java и JSR-223 для запуска кода Python (или Ruby) на сервере Coldfusion

Я могу создать объекты и перечислить их методы в порядке, однако я застрял в разных типах объектов.

Пример, который я пытаюсь получить работу в Coldfusion является

import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 
import javax.script.ScriptException; 

public class JSR223 { 

    public static void main(String[] args) throws ScriptException { 
     ScriptEngine engine = new ScriptEngineManager().getEngineByName("python"); 
     engine.eval("import sys"); 
     engine.eval("print sys"); 
     engine.put("a", 42); 
     engine.eval("print a"); 
     engine.eval("x = 2 + 2"); 
     Object x = engine.get("x"); 
     System.out.println("x: " + x); 
    } 
} 

То, что я до сих пор в CFML

ScriptEngine  = CreateObject("java", "javax.script.ScriptEngine"); 
ScriptEngineManager = CreateObject("java", "javax.script.ScriptEngineManager"); 
ScriptException  = CreateObject("java", "javax.script.ScriptException"); 

Часть я застрял на

ScriptEngine engine = new ScriptEngineManager().getEngineByName("python"); 

Как я могу создать это в CFML?

Edit:

engine = ScriptEngineManager.getEngineByName("python"); 
writeDump(engine); 

дает мне ошибку: переменная [ENGINE] не существует

Как другой класс, ScriptEngine вписывается в это?

ScriptEngine ScriptEngineManager

Update

я могу загрузить другие классы Python, так что я думаю, что баночка правильно установлен. т.е. со следующим кодом я могу сбросить объект interp.

Однако даже тогда вызов метода дает мне эту ошибку

java.lang.NullPointerException 
+0

* запустить код Python на сервере Coldfusion * Из любопытства, это что-то, что может/должно быть сделано в чистом cfml? – Leigh

+0

Это больше упражнение, чем что-либо другое. Я хотел бы иметь возможность доступа к библиотекам python, которых нет в CFML. – username

ответ

1

Ключевое слово new вызывает конструктор класса. ColdFusion не поддерживает new с java-объектами. Вместо этого используйте psuedo-method init():

The init method is not a method of the object, but a ColdFusion identifier that calls the new function on the class constructor.

буквальным перевод этого кода в цепочке вызовов. Сначала вызовите init(), чтобы создать новый экземпляр. Затем вызовите getEngineByName() этого экземпляра:

engine = createObject("java", "javax.script.ScriptEngineManager").init().getEngineByName("python"); 

Хотя для лучшей читаемости, вы можете захотеть разбить его:

ScriptEngineManager = createObject("java", "javax.script.ScriptEngineManager").init(); 
engine = ScriptEngineManager.getEngineByName("python"); 

Как и в сторону, в этом конкретном случае, вы можете технически оставьте вызов init().ColdFusion будет автоматически вызывать конструктор без аргументов, как только вы звоните getEngineByName():

...If you call a public non-static method on the object without first calling the init method, ColdFusion makes an implicit call to the default constructor.

Обновление на основе комментариев:

Если engine не определено, что означает «питон» двигатель был не найдено. Убедитесь, что файл added the the jython jar указан в пути класса CF (или загружен через this.javaSettings в ваш Application.cfc). После регистрации код должен работать правильно. По какой-то причине это не работает, если вы загружаете банку динамически через ACF this.javaSettings. Тем не менее, он отлично работает, если вы поместите jython jar в WEB-INF\lib и перезапустите CF. Попробуйте добавить банку в физический путь класса CF, а не загружать ее динамически, и она должна работать правильно.

Он также работает от CF, если вы сначала зарегистрируете двигатель первым (см. Ниже). Не уверен, почему этот дополнительный шаг необходим, когда ScriptEngineManager вызывается в CF, но не из Eclipse.

ScriptEngineManager = createObject("java", "javax.script.ScriptEngineManager").init(); 
factory = createObject("java", "org.python.jsr223.PyScriptEngineFactory").init(); 
ScriptEngineManager.registerEngineName("python", factory); 
engine = ScriptEngineManager.getEngineByName("python"); 
// ... 

How does the other class, ScriptEngine fit in with this?

В отличие от CF, Java является строго типизированным. Это означает, что когда вы объявляете переменную, вы также должны объявлять ее тип (или класс). Исходный код объявляет переменную engine как экземпляр класса ScriptEngine. Так как CF слабо типизирован, это необязательно. Просто объявите имя переменной как обычно. getEngineByName() method автоматически возвращает объект ScriptEngine (по определению в API).

+0

Я отредактировал вопрос, чтобы показать, где он не работал. Я не понимаю, как класс ScriptEngine вписывается в это. – username

+0

Если 'engine' не определен, это означает, что [двигатель python не найден] (http://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngineManager.html#getEngineByName (java. lang.String)). Работает ли исходный пример для вас в java? – Leigh

+0

jython работает нормально. Я добавил cfdumps ScriptEngine и ScriptEngineManager. – username

1

Мне удалось получить пример Лия, работающий в Lucee, используя следующий код и помещая банку в тот же каталог, что и файл .cfm. Я изначально помещал его в ту же папку, что и барабан Lucee, но он работал только частично.

ScriptEngineManager = createObject('java','javax.script.ScriptEngineManager').init(); 
factory = createObject('java','org.python.jsr223.PyScriptEngineFactory','jython-standalone-2.7.0.jar').init(); 
ScriptEngineManager.registerEngineName("python", factory); 
engine = ScriptEngineManager.getEngineByName("python"); 

engine.eval("x = 2 + 2"); 
x = engine.get("x"); 

writeDump(x); 
+0

Спасибо за отправку рабочего кода Люси. RE: * изначально поместил его в ту же папку ... *. Вы должны иметь возможность размещать файлы jar в любом месте, доступном для CF-движка. Может быть, вы забыли указать полный путь к файлу jar в createObject()? – Leigh

+0

Это может быть так. Я не указал полный путь в createObject, однако первоначальное создание объекта все еще работало. – username

+0

Да, любой из классов 'javax.script. *' Всегда будет работать. Этот lib связан с JRE и не требует дополнительных банок. Для пользовательских lib, таких как jython, полезно указать полный путь к банке, даже если это не требуется. Тогда вам не нужно угадывать, как ACF/Lucee разрешает относительный путь. Если переносимость является проблемой, просто используйте ExpandPath ("./ jython-standalone-2.7.0.jar"). – Leigh

Смежные вопросы