我正在开发一个 ADF Fusion Web 应用程序,其中包含一个带有 JDeveloper 11.1.1.4.0 的消息传递模块。我搜索了进行服务器端推送的技术(也问了一个关于它的问题)我搜索了“彗星”、服务器端推送等。我找到了Active Data Service和一些聊天或服务器端推送示例:
- http://biemond.blogspot.com/2009/12/adf-data-push-with-active-data-service.html
- https://blogs.oracle.com/adffun/entry/building_a_real_time_twitter_client_with_adf
我按照biemond 博客中的说明进行 ADS 的配置
将 ads conf 添加到 ADF META-INF/services 文件夹下的 adf-config.xml
<ads:adf-activedata-config xmlns="http://xmlns.oracle.com/adf/activedata/config">
<transport>long-polling</transport>
<latency-threshold>10000</latency-threshold>
<keep-alive-interval>10000</keep-alive-interval>
<polling-interval>3000</polling-interval>
<max-reconnect-attempt-time>1800000</max-reconnect-attempt-time>
<reconnect-wait-time>10000</reconnect-wait-time></ads:adf-activedata-config>
并创建了 adf-config.properties 文件
http\://xmlns.oracle.com/adf/activedata/config=oracle.adfinternal.view.faces.activedata.ActiveDataConfiguration$ActiveDataConfigCallback
并在 jsf 页面中创建了一个表。
<af:table value="#{MessageModel}" var="row"
rows="#{bindings.MessageVO.rangeSize}"
emptyText="#{bindings.MessageVO.viewable ? 'No data to display.' : 'Access Denied.'}"
fetchSize="#{bindings.MessageVO.rangeSize}"
rowBandingInterval="0" id="t1">
<af:column sortProperty="id" sortable="false"
headerText="#{bindings.MessageVO.hints.id.label}"
id="c1">
<af:outputText value="#{row.id}" id="ot2">
<af:convertNumber groupingUsed="false"
pattern="#{bindings.MessageVO.hints.id.format}"/>
</af:outputText>
</af:column>
<af:column sortProperty="Title" sortable="false"
headerText="#{bindings.MessageVO.hints.Title.label}"
id="c2">
<af:outputText value="#{row.title}" id="ot3"/>
</af:column>
</af:table>
并创建了 MessageModel 类,该类用作 jsff 中的表值。
public class MessageModel extends ActiveCollectionModelDecorator {
private MessageActiveDataModel activeDataModel = new MessageActiveDataModel();
private CollectionModel model = null;
public CollectionModel getCollectionModel() {
if (model == null) {
DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
FacesCtrlHierBinding treeData = (FacesCtrlHierBinding)dcBindings.getControlBinding("MessageVO");
model = treeData.getCollectionModel();
}
return model;
}
public MessageActiveDataModel getActiveDataModel() {
return activeDataModel;
}
public MessageActiveDataModel getMessageActiveDataModel() {
return activeDataModel;
}
}
和一个 ActiveDataModel 类
public class MessageActiveDataModel extends BaseActiveDataModel {
private final AtomicInteger listenerCount = new AtomicInteger(0);
private final AtomicInteger currEventId = new AtomicInteger();
protected void startActiveData(Collection<Object> rowKeys,
int startChangeCount) {
listenerCount.incrementAndGet();
if (listenerCount.get() == 1) {
System.out.println("start up");
Runnable dataChanger = new Runnable() {
public void run() {
System.out.println("MyThread starting.");
try {
Thread.sleep(2000);
System.out.println("thread running");
Change chg = new Change();
chg.triggerDataChange(MessageActiveDataModel.this);
} catch (Exception exc) {
System.out.println("MyThread exceptioned out.");
}
System.out.println("MyThread terminating.");
}
};
Thread newThrd = new Thread(dataChanger);
newThrd.start();
}
}
protected void stopActiveData(Collection<Object> rowKeys) {
listenerCount.decrementAndGet();
if (listenerCount.get() == 0) {
System.out.println("tear down");
}
}
public int getCurrentChangeCount() {
return currEventId.get();
}
public void bumpChangeCount() {
currEventId.incrementAndGet();
}
public void dataChanged(ActiveDataUpdateEvent event) {
fireActiveDataUpdate(event);
}
}
ActiveDataModel 类中的线程触发了一个名为 Change 的类
public class Change {
public Change() {
}
public void triggerDataChange(MessageActiveDataModel model) throws Exception {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(4000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
model.bumpChangeCount();
ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.UPDATE,
model.getCurrentChangeCount(),
JboActiveDataEventUtil.convertKeyPath(new Object[] { new Long(1),
new Integer(0) }),
null,
new String[] { "title" },
new Object[] { "Administration" });
model.dataChanged(event);
}
}
}
当我运行应用程序时,我可以在表中看到 MessageVO 中的行。它进入模型类、活动数据模型类和更改类,更改 ActiveDataMode 类中的 listenerCount 和 currentEventId 值。当我更新数据库中的行时,它不会触发更改事件,也不会检测数据库中的更新。
有没有人知道如何监听数据库的变化并根据 ADF 中的数据库变化进行服务器端推送?
提前致谢。