背景
我正在为各种服务提供商建立一个中央预约系统。这是基于 GlassFish 3.1.1 上的 Java EE 6 构建的,利用了 JSF 2、EJB 3.1 和其他 JEE6 标准。每个服务提供商都有自己的预约设备,在连接到互联网的服务器上运行,但目前他们没有任何界面允许患者自行预约。
我的系统将通过我定义的 API 在服务提供商的系统上同步预约(响应用户请求),该 API 涉及通过 HTTP 传输 XML 流。这些预约请求是同步的,因为服务提供商将继续以老式方式(通过电话/柜台)直接在其系统中进行预约,并且无论出于何种原因,他们的系统保留拒绝此类请求的权利(以防止重复预订和由于其他原因)。因此,他们的系统保留了真理来源的地位。
出于明显的原因(主要是安全性),API 连接是由服务提供商的系统建立的。这意味着请求由服务器(我的系统)发送,并由客户端(他们的系统)响应。
问题
我需要一些关于如何在 GlassFish 3.1.1 上使用 Java EE 6 通过 HTTP API 构建服务器推送 XML 的建议。我想到了许多不太理想的选择。其中一个涉及一个单例 bean,其中包含我的预约 ID 到他们的预约响应的映射。在这种情况下,我的系统会在有限的时间内(例如,最多 10 秒)轮询地图,直到找到匹配的响应,然后返回该响应,最终在 JSF UI 中处理该响应。同时,API servlet(或者也许是 JAX-RS Web 服务)轮询单例 bean 的请求,将它们转换为 XML 并将它们流式传输到服务提供者的输出流。
我确信一定有许多更好的方法可以做到这一点,而不涉及每个连接的线程、阻塞、轮询等。
有什么想法吗?
更新
我倾向于 Atmosphere/Jersey,但现在我意识到阻塞 I/O 在 NPTL 下是相当可扩展的,所以我在这方面很灵活。
Background
I'm well into building a central appointment booking system for various service providers. This is being built on Java EE 6 on GlassFish 3.1.1, making use of JSF 2, EJB 3.1 and other JEE6 standards. Each service provider has their own appointment booking facility running on their own server that is connected to the Internet, but currently they don't have any interface to allow their patients to make their own appointments.
My system will synchronously book appointments on service providers' systems (in response to user requests) via an API I have defined which involves streaming XML over HTTP. These appointment booking requests are synchronous because service providers will continue to book appointments directly in their system the old fashioned way (over the phone/counter) and, for whatever reasons, their system reserves the right to reject such requests (to prevent double bookings and for other reasons). So, their systems retain the status of being the source of truth.
For obvious reasons (mainly security), API connections are established by the service providers' systems. This means requests are being sent by the server (my system) and responses by the client (their system).
Problem
I need some suggestions regarding how I can build a server-push XML over HTTP API using Java EE 6 on GlassFish 3.1.1. A number of less than ideal options come to mind. One of them involves a singleton bean that contains a map of my appointment IDs to their appointment booking responses. In this scenario, my system polls the map for a limited time (up to 10 seconds, for example) until it finds a matching response, then returns the response which is then handled eventually in the JSF UI. Meanwhile, the API servlet (or perhaps JAX-RS web service) polls the singleton bean for requests, converts them to XML and streams them to the service provider's output stream.
I'm sure there must be a number of better ways of doing this not involving thread-per-connection, blocking, polling, etc.
Ideas?
Update
I was leaning towards Atmosphere/Jersey, but now I realize that blocking I/O is quite scalable under NPTL, so I'm flexible in that regard.
发布评论
评论(1)
我是这样做的:
从包含以下内容的单例 EJB 开始:
Map>
,其中键是 API 客户端 ID;Map>
,其中键是 Web 端约会 ID,AppointmentExchange
包含该 ID 和 API 客户端约会 ID。我在单例 EJB 上设置了 bean 管理的并发控制,定义了一些入队、出队和重新入队的方法(后者是为了防止
OutboundApiMessage
的服务器推送失败,需要将其添加到队列的前面,其中它将是下一个要出队的项目),将其连接到 JAX-RS Web 服务(一个用于上游,一个用于下游)。单例 EJB 有一个同步预约的方法。它将消息放入队列以供客户端选取,创建一个包含新的
AppointmentExchange
实例的Exchanger
,然后阻塞等待交换。当入站 Web 服务返回答案时,该 Web 服务会通过另一种方法通知单例 EJB,该方法通过Exchanger
执行交换。现在一切都运转良好。当然,还有更多的内容,但这就是要点。
Here's how I did it:
Start with a singleton EJB containing:
Map<Long, BlockingDeque<OutboundApiMessage>>
, where the key is the API client ID;Map<Long, Exchanger<AppointmentExchange>>
, where the key is the web-side appointment ID andAppointmentExchange
contains that ID and the API client side appointment ID.I set bean managed concurrency control on the singleton EJB, defined some methods to enqueue, dequeue and requeue (the latter in case server push of the
OutboundApiMessage
failed and needed to be added to the front of the queue where it would be the next item to be dequeued), wired it to the JAX-RS web services (one for upstream, one for downstream).The singleton EJB has a method to synchronously book an appointment. It enqueues a message to be picked up by the client, creates an
Exchanger
containing a newAppointmentExchange
instance then blocks waiting for the exchange. When an answer comes back on the inbound web service, that web service notifies the singleton EJB via another method which performs the exchange via theExchanger
.It all works quite well now. Of course, there is a bit more to it than that, but that's the gist of it.