nodejs在java中应用,我应该如何从Java应用程序运行NodeJS?

I'm writing a Java library, actually, a Clojure library, but for this question, what matters is that it runs on the JVM. This library needs to execute some JavaScript. I tried with Nashorn but I encounter some limitations that might be too hard to overcome. As an alternative, I want to try NodeJS.

I want my library to be self contained, to not depend on the system running NodeJS independently and thus requiring a particular deployment mechanism to place the Java and NodeJS artifacts in the right places to be picked up by the two different network servers. This approach, though, brings some issues.

I will be talking to NodeJS over HTTP but I don't want NodeJS to open a specific port. I want to find a random unused one so there's no collisions. I also want to control where the logs from NodeJS go, as to keep them with the rest of my application. Lastly, my app should be able to detect when NodeJS crashed and re-run it or report an error with information.

What's the best way to approach this? Are there any Java libraries to help manage child process in this fashion? Anything in particular I should do from the NodeJS side (I'm very new to NodeJS, I never used it before).

解决方案

My solution in the end was to use ProcessBuilder like this:

(defn create-process-builder [js-engine]

(doto (ProcessBuilder. ["node" (:path js-engine)

"--port-file" (:port-file js-engine)

"--default-ajax-host" (:default-ajax-host js-engine)

"--default-ajax-port" (str (:default-ajax-port js-engine))])

.inheritIO))

and then call start in it. inheritIO causes the output of it to go to the output of the current process which effectively merges stdout and stderr.

On top of that NodeJS opens a random port by specifying 0 as the port number and writes it to a file:

(let [app (-> (express)

(.use (cookie-parser))

(.get "/" (fn [_req res] (.send res "Universal JavaScript engine for server side pre-rendering single page applications.")))

(.get "/render" render))

server (.createServer http app)]

(.listen server 0 (fn [] (.writeFile fs (:port-file options) (.-port (.address server)))))))))

which then is opened by the Java side (waiting for it to appear):

(defn get-port-number [js-engine]

(or (with-timeout

(:start-timeout js-engine)

(loop [port-number (read-port-file js-engine)]

(if (string/blank? port-number)

(if (is-running? js-engine)

(do (Thread/sleep 100)

(recur (read-port-file js-engine)))

(throw (Exception. (str "While waiting for port number, process died: " (:path js-engine)))))

port-number)))

(throw (Exception. (str "Waited for " (:start-timeout js-engine) " for " (:path js-engine) " to start and report its port number but it timed out.")))))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值