[richfaces-issues] [JBoss JIRA] (RF-13674) a4j:push broken on WebLogic 12c
Val Blant (JIRA)
issues at jboss.org
Mon Jun 16 21:21:24 EDT 2014
[ https://issues.jboss.org/browse/RF-13674?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Val Blant updated RF-13674:
---------------------------
Description:
<a4j:push /> works properly on Tomcat 7, but fails on WebLogic 12c.
{code:title=Page.xhtml|borderStyle=solid}
<a4j:push address="systemLinks" >
<a4j:ajax event="dataavailable" render="systemLinksPanel" />
</a4j:push>
<a4j:outputPanel id="systemLinksPanel">
stuff here
</a4j:outputPanel>
{code}
{code:title=Java Code}
TopicKey topicKey = new TopicKey("systemLinks");
TopicsContext topicsContext = TopicsContext.lookup();
topicsContext.publish(topicKey, "fly, you fools!");
{code}
On Tomcat 7 this work perfectly, and always refreshes '_systemLinksPanel_' when data is published.
On Weblogic 12c the data is not flushed correctly. If you use Wireshark, you'd see the following response coming back from the server:
{panel:title=Tomcat 7}
3b
<"topic":"systemLinks","data":"fly, you fools!","number":0>
0
{panel}
{panel:title=Weblogic 12c}
003b
<"topic":"systemLinks","data":"fly, you fools!","number":0>
{panel}
*Note the missing zero terminator line in the WebLogic response!*
I narrowed down the problem to the following:
{code:title=org.richfaces.application.push.impl.RequestImpl}
public synchronized void onBroadcast(AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) {
MessageDataScriptString serializedMessages = (MessageDataScriptString) event.getMessage();
getSession().clearBroadcastedMessages(serializedMessages.getLastSequenceNumber());
hasActiveBroadcaster = false;
if (isPolling()) {
event.getResource().resume(); // <= THIS LINE
} else {
postMessages();
}
}
{code}
There is nothing wrong with this in principle, but it does not work due to a bug in Atmosphere 0.8.4. Calling _AtmosphereResource.resume()_ at this point seems reasonable, since it is supposed to properly finish/commit the _HttpServletResponse_. However, this does not work on WebLogic 12c and leads to incorrectly flushed data demonstrated above.
The underlying problem seems to be the fact that _AtmosphereResource.resume()_ method interrupts the thread which flushed the socket Writer before a call to _asyncContext.complete()_ is made:
{code}
public AtmosphereResource resume() {
....
if (!b.isDestroyed()) {
b.removeAtmosphereResource(event.getResource());
}
....
asyncSupport.action(this); // <= This is where asyncContext.complete() is called
}
{code}
I have verified that calling _asyncContext.complete()_ before we clean up Atmosphere resources fixes the problem.
Here's the fix, which needs to go into _RequestImpl.onBroadcast_:
{code:title=org.richfaces.application.push.impl.RequestImpl}
public synchronized void onBroadcast(AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) {
..............
if (isPolling()) {
// This is the workaround. Completing AsyncContext before cleaning up Atmosphere resources
// seems to make this work everywhere.
//
AsyncContext asyncContext = (AsyncContext)
event
.getResource()
.getRequest()
.getAttribute("org.atmosphere.container.asyncContext");
if ( asyncContext != null ) {
asyncContext.complete();
}
event.getResource().resume();
} else {
postMessages();
}
}
..............
{code}
I am attaching a very simple WAR file that demonstrates the problem clearly. The demo app does not use Richfaces, b/c I wanted to remove all unnecessary complexity. Instead I created a couple of simple classes that mimic the behavior of _org.richfaces.webapp.PushHandlerFilter_ and _org.richfaces.application.push.impl.RequestImpl_. In the demo app, _MeteorRequest = RequestImpl_, which is where the fix needs to go.
Please note that according to the Atmosphere author, this problem is fixed in 2.1 branch. Here's the discussion: https://groups.google.com/forum/#!topic/atmosphere-framework/KCKlSmbMrRo
was:
<a4j:push /> works properly on Tomcat 7, but fails on WebLogic 12c.
{code:title=Page.xhtml|borderStyle=solid}
<a4j:push address="systemLinks" >
<a4j:ajax event="dataavailable" render="systemLinksPanel" />
</a4j:push>
<a4j:outputPanel id="systemLinksPanel">
stuff here
</a4j:outputPanel>
{code}
{code:title=Java Code}
TopicKey topicKey = new TopicKey("systemLinks");
TopicsContext topicsContext = TopicsContext.lookup();
topicsContext.publish(topicKey, "fly, you fools!");
{code}
On Tomcat 7 this work perfectly, and always refreshes '_systemLinksPanel_' when data is published.
On Weblogic 12c the data is not flushed correctly. If you use Wireshark, you'd see the following response coming back from the server:
{panel:title=Tomcat 7}
3b
<"topic":"systemLinks","data":"fly, you fools!","number":0>
0
{panel}
{panel:title=Weblogic 12c}
003b
<"topic":"systemLinks","data":"fly, you fools!","number":0>
{panel}
*Note the missing zero terminator line in the WebLogic response!*
I narrowed down the problem to the following:
{code:title=org.richfaces.application.push.impl.RequestImpl}
public synchronized void onBroadcast(AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) {
MessageDataScriptString serializedMessages = (MessageDataScriptString) event.getMessage();
getSession().clearBroadcastedMessages(serializedMessages.getLastSequenceNumber());
hasActiveBroadcaster = false;
if (isPolling()) {
event.getResource().resume(); // <= THIS LINE
} else {
postMessages();
}
}
{code}
There is nothing wrong with this in principle, but it does not work due to a bug in Atmosphere 0.8.4. Calling _AtmosphereResource.resume()_ at this point seems reasonable, since it is supposed to properly finish/commit the _HttpServletResponse_. However, this does not work on WebLogic 12c and leads to incorrectly flushed data demonstrated above.
The underlying problem seems to be the fact that _AtmosphereResource.resume()_ method interrupts the thread which flushed the socket Writer before a call to _asyncContext.complete()_ is made:
{code}
public AtmosphereResource resume() {
....
if (!b.isDestroyed()) {
b.removeAtmosphereResource(event.getResource());
}
....
asyncSupport.action(this); // <= This is where asyncContext.complete() is called
}
{code}
I have verified that calling _asyncContext.complete()_ before we clean up Atmosphere resources fixes the problem.
Here's the fix, which needs to go into _RequestImpl.onBroadcast_:
{code:title=org.richfaces.application.push.impl.RequestImpl}
public synchronized void onBroadcast(AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) {
..............
if (isPolling()) {
// This is the workaround. Completing AsyncContext before cleaning up Atmosphere resources
// seems to make this work everywhere.
//
AsyncContext asyncContext = (AsyncContext)
event
.getResource()
.getRequest()
.getAttribute("org.atmosphere.container.asyncContext");
if ( asyncContext != null ) {
asyncContext.complete();
}
event.getResource().resume();
} else {
postMessages();
}
}
..............
{code}
I am attaching a very simple WAR file that demonstrates the problem clearly. The demo app does not use Richfaces, b/c I wanted to remove all unnecessary complexity. Instead I created a couple of simple classes that mimic the behavior of _org.richfaces.webapp.PushHandlerFilter_ and _org.richfaces.application.push.impl.RequestImpl_. In the demo app, _MeteorRequest = RequestImpl_, which is where the fix needs to go.
> a4j:push broken on WebLogic 12c
> -------------------------------
>
> Key: RF-13674
> URL: https://issues.jboss.org/browse/RF-13674
> Project: RichFaces
> Issue Type: Bug
> Security Level: Public(Everyone can see)
> Components: component-push/poll
> Affects Versions: 4.2.0.Final
> Environment: WebLogic 12c
> Reporter: Val Blant
> Attachments: atmosphere-weblogic12c-bug-0.8.4-sources.jar, atmosphere-weblogic12c-bug-0.8.4.war
>
>
> <a4j:push /> works properly on Tomcat 7, but fails on WebLogic 12c.
> {code:title=Page.xhtml|borderStyle=solid}
> <a4j:push address="systemLinks" >
> <a4j:ajax event="dataavailable" render="systemLinksPanel" />
> </a4j:push>
>
> <a4j:outputPanel id="systemLinksPanel">
> stuff here
> </a4j:outputPanel>
> {code}
> {code:title=Java Code}
> TopicKey topicKey = new TopicKey("systemLinks");
> TopicsContext topicsContext = TopicsContext.lookup();
> topicsContext.publish(topicKey, "fly, you fools!");
> {code}
> On Tomcat 7 this work perfectly, and always refreshes '_systemLinksPanel_' when data is published.
> On Weblogic 12c the data is not flushed correctly. If you use Wireshark, you'd see the following response coming back from the server:
> {panel:title=Tomcat 7}
> 3b
> <"topic":"systemLinks","data":"fly, you fools!","number":0>
> 0
> {panel}
> {panel:title=Weblogic 12c}
> 003b
> <"topic":"systemLinks","data":"fly, you fools!","number":0>
> {panel}
> *Note the missing zero terminator line in the WebLogic response!*
> I narrowed down the problem to the following:
> {code:title=org.richfaces.application.push.impl.RequestImpl}
> public synchronized void onBroadcast(AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) {
> MessageDataScriptString serializedMessages = (MessageDataScriptString) event.getMessage();
> getSession().clearBroadcastedMessages(serializedMessages.getLastSequenceNumber());
> hasActiveBroadcaster = false;
> if (isPolling()) {
> event.getResource().resume(); // <= THIS LINE
> } else {
> postMessages();
> }
> }
> {code}
> There is nothing wrong with this in principle, but it does not work due to a bug in Atmosphere 0.8.4. Calling _AtmosphereResource.resume()_ at this point seems reasonable, since it is supposed to properly finish/commit the _HttpServletResponse_. However, this does not work on WebLogic 12c and leads to incorrectly flushed data demonstrated above.
> The underlying problem seems to be the fact that _AtmosphereResource.resume()_ method interrupts the thread which flushed the socket Writer before a call to _asyncContext.complete()_ is made:
> {code}
> public AtmosphereResource resume() {
> ....
> if (!b.isDestroyed()) {
> b.removeAtmosphereResource(event.getResource());
> }
> ....
> asyncSupport.action(this); // <= This is where asyncContext.complete() is called
> }
> {code}
> I have verified that calling _asyncContext.complete()_ before we clean up Atmosphere resources fixes the problem.
> Here's the fix, which needs to go into _RequestImpl.onBroadcast_:
> {code:title=org.richfaces.application.push.impl.RequestImpl}
> public synchronized void onBroadcast(AtmosphereResourceEvent<HttpServletRequest, HttpServletResponse> event) {
> ..............
> if (isPolling()) {
> // This is the workaround. Completing AsyncContext before cleaning up Atmosphere resources
> // seems to make this work everywhere.
> //
> AsyncContext asyncContext = (AsyncContext)
> event
> .getResource()
> .getRequest()
> .getAttribute("org.atmosphere.container.asyncContext");
> if ( asyncContext != null ) {
> asyncContext.complete();
> }
> event.getResource().resume();
> } else {
> postMessages();
> }
> }
> ..............
> {code}
> I am attaching a very simple WAR file that demonstrates the problem clearly. The demo app does not use Richfaces, b/c I wanted to remove all unnecessary complexity. Instead I created a couple of simple classes that mimic the behavior of _org.richfaces.webapp.PushHandlerFilter_ and _org.richfaces.application.push.impl.RequestImpl_. In the demo app, _MeteorRequest = RequestImpl_, which is where the fix needs to go.
> Please note that according to the Atmosphere author, this problem is fixed in 2.1 branch. Here's the discussion: https://groups.google.com/forum/#!topic/atmosphere-framework/KCKlSmbMrRo
--
This message was sent by Atlassian JIRA
(v6.2.6#6264)
More information about the richfaces-issues
mailing list