我们的服务器上有2个应用程序。一个是Java应用程序,用普通英语编写的句子中提取重要的信息块。它应该只与我们服务器上的其他应用程序通信(尽管我们还没有设置防火墙来保护它)。它不应该与公众交谈(尽管目前是可能的)。它有一些非常简单的Java代码,它在端口8080上打开一个Socket然后监听。它希望收到一个可以转换为JSON的字符串。它发回一个可以转换为JSON的字符串。它不会发回任何HTTP头,它只是你能想象到的最简单的Socket代码,甚至不是30行代码。
我们有另一个用Clojure编写的应用程序,它通过RESTful API与广阔的世界交流。
基本思想是请求从外部世界进入我们的服务器,并与Clojure应用程序进行交互。 Clojure应用程序假设与Java应用程序交互,然后Clojure应用程序向任何查询它的人发回响应。
我无法弄清楚如何从Clojure应用程序中调用Java应用程序。我试图使用像clj-http这样的库,但它依赖于Apache HttpClient,它假设响应将包含正确的HTTP头。 Apache HttpClient在与Java应用程序交互时抛出了异常,因为Java应用程序只发回一个字符串(没有HTTP头)。我不想在Java应用程序中编写完整的HTTP代码,因为这与我们在Clojure应用程序中所做的工作相关。
所以,我改变了战术,并从Clojure方面编写了一些原始的Socket代码。该代码如下:
(def conn (ref {:in nil :out nil}))
(defn connect []
(let [socket (Socket. "localhost" 8080)
in (BufferedReader. (InputStreamReader. (.getInputStream socket)))
out (PrintWriter. (.getOutputStream socket))]
(dosync
(alter conn
(fn [old-value] (assoc old-value :in in)))
(alter conn
(fn [old-value] (assoc old-value :out out))))))
写函数是基本的:
(defn write-message [msg]
(doto (:out @conn)
(.println (str msg "\r"))
(.flush)))
这个工作过一次,但大部分时间我都尝试过(从浏览器,它使用Javascript来ping API,然后调用Java应用程序)我得到:
Connection reset stack trace:
{:class java.net.SocketException,
:message "Connection reset",
:trace-elems ({:method "read",
:class "java.net.SocketInputStream",
当我这样做时,我打开了几个终端窗口。 Java应用程序的终端根本没有显示任何活动,而Clojure应用程序显示上述错误。
如果我使用这个curl(直接点击Java应用程序),那么一切正常:
curl --verbose "http://localhost:8080" -d ' { "transaction-id" : "99393920", "report" : "Allie Hanther of IBM responded to our proposal and said her company is ready to move forward. The deal is worth $400,000 annually. I will meet with her tomorrow and we will sign the contract." } ' -X POST --header "Content-Type:application/json"
我意识到像“POST”和“content type”这样的东西在这种情况下毫无意义,因为我们不是在谈论HTTP服务器。不过,他们似乎没有任何伤害。此curl请求返回正确的响应。
但是Clojure应用程序只会出错。
我可以相信这2个应用程序与端口8080存在冲突,但我不明白该冲突的性质。
有什么建议吗?
将来,我们认为我们将放弃Socket,而是使用Redis或作业队列进行通信,但是现在我们正在使用Socket,我想让它正常工作。
现在我只需要Clojure应用程序像curl一样工作。