BlazeDS,推送消息会生成IllegalStateException

时间:2018-04-27 20:23:32

标签: java flex tomcat6 blazeds

我在 Tomcat 6 上运行 Flex 3.6 + BlazeDS + Java 1.6 webapp。我需要BlazeDS从服务器推送消息服务,以便在用户从flex前端调用某些详细信息时创建确定性进度条。

然后我有如下构建的n模块:

public static const JOBN:String = "JOBN";
private var _dm:DataManager;

public function init():void {
  _dm = new DataManager;
}
private function btnN_OnClick(event:MouseEvent):void {
  _dm.addEventListener(JOBN, onJobNResult);
  _dm.jobN();
}
private function onJobNResult(dataEvent:MyEvent):void {
  var resN:int = dataEvent.result as int;
  _dm.removeEventListener(JOBN, onJobNResult);
}

和构建如下的DataManager:

    public static const JOBN:String = "JOBN";

    public function DataManager() {
        var loCs:ChannelSet = new ChannelSet();
        loCs.addChannel(new AMFChannel("canale", "messagebroker/amf"));
        _service = new RemoteObject("dataManager");
        _service.channelSet = loCs;
    }

    public function jobN():void {
        var token:AsyncToken = _service.jobN();
        token.addResponder(new AsyncResponder(jobNOnResult,jobNOnFault));
        runProgressBar();
    }
    private function jobNOnFault(event:FaultEvent,token:Object):void {
        var _fail:String = "Error";
    }
    private function jobNOnResult(event:ResultEvent,token:Object):void {
        var jobNResult:int = event.result as int;
        dispatchEvent(new MyEvent(JOBN,jobNResult));
        stopProgressBar();
    }

runProgressBar() stopProgressBar() 方法分别创建和删除包含进度的PopUp栏和放置在应用程序画布上。弹出方法启动和停止推送消息线程:

private function init():void {
   start();
}
private function start():void {
   var msg:AsyncMessage = new AsyncMessage();
   msg.body = "START";
   producer.send(msg);
   consumer.subscribe();
}
private function stop():void {
   var msg:AsyncMessage = new AsyncMessage();
   msg.body = "STOP";
   producer.send(msg);
}
private function messageHandler(message:IMessage):void {
   values = message.body as String;
   value = (int) (values.substr(0, values.lastIndexOf(";")));
   max = (int) (values.substr(values.indexOf(";")+1,values.length));
   if (value == -1) {
     value = 0;
     increaseProgress(max,max);
     stop();
   } else {
     increaseProgress(value, max);
   }
}
private function ack(event:MessageAckEvent):void {
    if ( (event != null) && (event.message.body != null) ) {
    values = event.message.body as String;
    }
}
private function increaseProgress(num:int, max:int):void {
    trace(num+" "+max);
    prgBar.setProgress(num, max);
}

发送数据的Java类:

public class ProgressMessSender extends ServiceAdapter {
private ProgressDataSender thread;

public void startMessaging() {
    if (thread == null) {
        thread = new ProgressDataSender();
        thread.start();
        }
}
public void stop() {
    thread.running = false;
    MsgConstant.ProgValues = 0;
    MsgConstant.MaxValues = -2;
    thread = null;
}
@Override
public Object invoke(Message message) {
    if (message.getBody().equals("STOP")) {
        stop();
    } else if (message.getBody().equals("START")) {
        startMessaging();
    }
    return null;
}

public class ProgressDataSender extends Thread {
    public volatile boolean running = true;
    private Message createTestMessage() {
        AsyncMessage msg = new AsyncMessage();
        msg.setDestination("RandomDataPush");
        msg.setClientId(UUIDUtils.createUUID());
        msg.setMessageId(UUIDUtils.createUUID());
        msg.setBody(MsgConstant.ProgValues+";"+MsgConstant.MaxValues);
        return msg;
    }
    public void run() {
        while(running) {
            sendMessageToClients(createTestMessage());
            secondsToSleep(5);
        }
    }
    public void sendMessageToClients(Message msg) {
        ((MessageService) getDestination().getService()).pushMessageToClients(msg, false);
    }
    private void secondsToSleep(int seconds) {
        try{
            Thread.sleep(seconds * 10);
        }catch(InterruptedException e){
            System.out.println("TestServiceAdapter Interrupted while sending messages");
            e.printStackTrace();
        }
    }
}
}

MsgConstant.MaxValues MsgConstant.ProgValues 是在作业类中分别设置和增加的静态变量。配置BlazeDS文件 messaging-config.xml services-config.xml 将根据此{{ 3}}

问题 : 如果我从模块调用作业,进度条正确启动和停止,一切正常。一旦从模块中调用了一个作业,如果我从另一个模块调用另一个作业,我总会得到以下异常:

[BlazeDS]Unexpected error encountered in Message Broker servlet
java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:421)
at flex.messaging.endpoints.BaseStreamingHTTPEndpoint.handleFlexClientStreamingOpenRequest(BaseStreamingHTTPEndpoint.java:764)
at flex.messaging.endpoints.BaseStreamingHTTPEndpoint.serviceStreamingRequest(BaseStreamingHTTPEndpoint.java:1055)
at flex.messaging.endpoints.BaseStreamingHTTPEndpoint.service(BaseStreamingHTTPEndpoint.java:460)
at flex.messaging.MessageBrokerServlet.service(MessageBrokerServlet.java:353)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)

我在网上搜索过,但我找不到可行的解决方案,而且我不知道如何解决这个问题。

更简单的问题..我尝试了另一种方式来推送消息而不扩展 ServiceAdapter

消息-config.xml中:

<adapters>
    <adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" />
</adapters>

<destination id="feed"> 
    <properties> 
        <network>
            <session-timeout>0</session-timeout> 
        </network> 
        <server>
            <message-time-to-live>0</message-time-to-live> 
            <durable>false</durable> 
        </server> 
    </properties> 
</destination>

services-config.xml与第一个问题相同:

<channel-definition id="my-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">
        <endpoint url="http://localhost:8080/ProgressBar2/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>
        <properties>
             <!-- you don't need to set all these properties, this is just what we set, included for illustration, only -->
            <idle-timeout-minutes>0</idle-timeout-minutes>
            <max-streaming-clients>10</max-streaming-clients>
                <server-to-client-heartbeat-millis>5000</server-to-client-heartbeat-millis>
            <user-agent-settings>
                <user-agent match-on="Safari" kickstart-bytes="2048" max-streaming-connections-per-session="10"/>  
                <user-agent match-on="MSIE" kickstart-bytes="2048" max-streaming-connections-per-session="15"/> 
                <user-agent match-on="Firefox" kickstart-bytes="2048" max-streaming-connections-per-session="10"/>
            </user-agent-settings>
        </properties>
</channel-definition>

和推送消息的类:

private Message createTestMessage() {

    AsyncMessage msg = new AsyncMessage();
    msg.setDestination("feed");
    msg.setClientId(clientID);
    msg.setMessageId(UUIDUtils.createUUID());
    msg.setBody(MsgConstant.ProgValues+";"+MsgConstant.MaxValues);

    msgBroker.routeMessageToService(msg, null);

    System.out.println("CREATE MESSAGE FOR CLIENT: "+msg.getBody().toString());
    return msg;
}

public void run() {
    while(running) {
        createTestMessage();
        secondsToSleep(1);
    }
}


private void secondsToSleep(int seconds) {
    try{
        Thread.sleep(seconds * 100);
    }catch(InterruptedException e){
        System.out.println("TestServiceAdapter Interrupted while sending messages");
        e.printStackTrace();
    }
}

这种方式比第一种方式更好,但方法msgBroker.routeMessageToService()每隔一秒向客户端发送一条消息(或消息块),进度条在一段时间内从10%增加到50%或更多#39;不好。有没有办法快速发送消息?

解决方案

我设法将消息从服​​务器推送到客户端没有定义自定义SeviceAdapter(类内部的Thread扩展ServiceAdapter在应用程序启动时启动,我不知道如何避免这种情况)如下所示:

消息-config.xml中

<default-channels>
    <channel ref="my-streaming-amf"/>
    <channel ref="my-polling-amf"/>
</default-channels>


<destination id="dest">
    <properties> 
        <network>
            <session-timeout>0</session-timeout> 
        </network> 
        <server>
            <message-time-to-live>0</message-time-to-live> 
            <durable>false</durable> 
        </server>
    </properties>
</destination>

服务-config.xml中

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
        <endpoint url="http://localhost:8080/ProgressBar2/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
        <properties>
            <polling-enabled>false</polling-enabled>
            <polling-interval-millis>4</polling-interval-millis>
        </properties>
    </channel-definition>

<channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
        <endpoint url="http://localhost:8080/ProgressBar2/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
        <properties>
            <polling-enabled>false</polling-enabled>
            <polling-interval-seconds>4</polling-interval-seconds>
        </properties>
    </channel-definition>

    <!-- definito per il push di dati asincroni da java a flex -->
<channel-definition id="my-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">
        <endpoint url="http://localhost:8080/ProgressBar2/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>
        <properties>
             <!-- you don't need to set all these properties, this is just what we set, included for illustration, only -->
            <idle-timeout-minutes>0</idle-timeout-minutes>
            <max-streaming-clients>10</max-streaming-clients>
                <server-to-client-heartbeat-millis>5000</server-to-client-heartbeat-millis>
            <user-agent-settings>
                <user-agent match-on="Safari" kickstart-bytes="2048" max-streaming-connections-per-session="10"/>  
                <user-agent match-on="MSIE" kickstart-bytes="2048" max-streaming-connections-per-session="15"/> 
                <user-agent match-on="Firefox" kickstart-bytes="2048" max-streaming-connections-per-session="10"/>
            </user-agent-settings>
        </properties>
</channel-definition>

java类扩展发送消息的线程:

MessageBroker msgBroker = MessageBroker.getMessageBroker(null);
public Message createTestMessage() {

    AsyncMessage msg = new AsyncMessage();
    msg.setDestination("feed");
    msg.setClientId(UUIDUtils.createUUID());
    msg.setMessageId(UUIDUtils.createUUID());
    msg.setBody(MsgConstant.ProgValues+";"+MsgConstant.MaxValues);

    msgBroker.routeMessageToService(msg, null);

    return msg;
}

public void run() {
    while(running) {
        sendMessageToClients(createTestMessage());
        secondsToSleep(1);
    }
}

public void sendMessageToClients(Message msg) {
    MessageService service = (MessageService) msgBroker.getService("message-service");
    service.pushMessageToClients(msg, false);
}

我在.mxml中定义了一个标签 consumer ,并在精心设计开始时通过 DataManager 启动(并停止)线程。

0 个答案:

没有答案