Options

Classic Client, RoleTailored Client and MSMQ

aynalunaaynaluna Member Posts: 5
edited 2012-02-14 in NAV Three Tier
For the following Situation:
In Table 18 Customer
Trigger OnModify:
(...)
FMXIntegrationManagement.CreateMessage(Customer);
(...)

Where:
CreateMessage(Customer : Record Customer)
InitNavComCom();
IF NOT XMLPORT.EXPORT(XMLPORT::ACCMOD,OutS,Customer) THEN BEGIN
MESSAGE(Text002,XMLPORT::ACCMOD);
END;
IF NOT OutMsg.Send(0) THEN BEGIN
MESSAGE(Text003,XMLPORT::ACCMOD)
END;

Where :
InitNavComCom()
IF ISCLEAR(MQBus) AND ISCLEAR(CC2) THEN BEGIN
IF ISSERVICETIER THEN BEGIN
IF (NOT CREATE(MQBus,TRUE,TRUE)) OR (NOT CREATE(CC2,TRUE,TRUE)) THEN BEGIN
ERROR(Text001);
END;
END ELSE BEGIN
IF (NOT CREATE(MQBus,TRUE)) OR (NOT CREATE(CC2,TRUE)) THEN BEGIN
ERROR(Text001);
END;
END;
END;
CC2.AddBusAdapter(MQBus,1);
CompanyInformation.GET;
MQBus.OpenWriteQueue(CompanyInformation."FMX Trigger Queue Name",0,0);
OutMsg := CC2.CreateoutMessage('Message [url=queue://'+CompanyInformation]queue://'+CompanyInformation[/url]. Trigger Queue Name");
OutS := OutMsg.GetStream();

Variables:
Name DataType Subtype
MQBus Automation 'Navision MS-Message Queue BusAdapter'.MSMQBusAdapter
CC2 Automation 'Navision Communication Component version 2'.CommunicationComponent
OutMsg Automation 'Navision Communication Component version 2'.OutMessage
OutS OutStream
CompanyInformation Record Company Information

In Classic Client, results are as expected: modifying a Customer creates a Message.

But In RoleTailored Client, when pressing OK button after modfying a Customer record, the error:
"The Server net.[url=tcp://localhost:7046/DynamicsNAV/Service]tcp://localhost:7046/DynamicsNAV/Service[/url] is either unavailable or oyur connection has been lost. Do you want to attempt to reconnect?"

When choosing yes or no, the following error occurs: "The connection to the servers has been lost. The application will close."

Investigating a litle bit further, Computer Management -> System Tools -> Event Viewer -> Windows Logs-> Application, found the following error:

Service: MicrosoftDynamicsNavServer
User: aluna
Type: System.InvalidCastException
Message: Unable to cast object of type 'Microsoft.Dynamics.Nav.Runtime.NavAutomation' to type 'Microsoft.Dynamics.Nav.Runtime.NavStream'.
StackTrace:
at Microsoft.Dynamics.Nav.Runtime.NavAutomation.InvokeMethod[T](String methodName, Object[] arguments)
at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit50002.InitNavComCom()
at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit50002.CreateMessageACCMOD(INavRecordHandle customer)
at Microsoft.Dynamics.Nav.BusinessApplication.Codeunit50002.OnInvoke(Int32 memberId, Object[] args)
at Microsoft.Dynamics.Nav.Runtime.NavApplicationObjectBase.Invoke(Int32 methodId, Object[] arguments)
at Microsoft.Dynamics.Nav.BusinessApplication.Record18.OnModify()
at Microsoft.Dynamics.Nav.Runtime.NavRecord.Modify(DataError errorLevel, Boolean runApplicationTrigger, Boolean runGlobalTrigger)
at Microsoft.Dynamics.Nav.Service.NsDataAccess.Modify(DataError errorLevel, Boolean runApplicationTrigger)
at Microsoft.Dynamics.Nav.Service.NsFormDataAccess.Modify(DataError errorLevel, Boolean runTrigger)
at Microsoft.Dynamics.Nav.Service.NSRecord.Modify(NavConnection con)
at Microsoft.Dynamics.Nav.Service.NSService.<>c__DisplayClass2b.<ModifyRecord>b__2a(Connection connection)
at Microsoft.Dynamics.Nav.Service.NSService.ExecuteOperation[T](String operationName, ServiceOperation`1 operation, Connection connection, Boolean revertLanguageChanges, WindowsIdentity impersonationIdentity)
Source: Microsoft.Dynamics.Nav.Ncl
we think this exception is caused in InitNavComCom, Line OutS := OutMsg.GetStream();
Any ideas on how to resolve it? Help would be really apreciated.

Comments

  • Options
    rdebathrdebath Member Posts: 383
    You're creating the automation objects on the client machine not the server. This means that the stream variable will have to be remoted through the connection between the service tier and the RTC I don't think this is allowed.

    It'd be easiest if you can create the automation objects on the server. If you actually need to send the message from the client I think you're going to have to write your own COM object or addin.
  • Options
    aynalunaaynaluna Member Posts: 5
    I did tried creating the automation in the server (CREATE(AUTOMAT,TRUE,FALSE) and CREATE(AUTOMAT,FALSE,FALSE))
    And still errors, but with: The call to member Send failed. there is insufficent memory to perform the operation on the stream
  • Options
    rdebathrdebath Member Posts: 383
    Hmmm, perhaps; are you trying to send a message of more the 4 megabytes?

    MSMQ has a 4MB limit on the size of the message and XML is very verbose. (Do you hate XML yet! :D )

    Then there's these: http://blogs.msdn.com/johnbreakwell/arc ... -away.aspx

    One important point though; does the Classic client still work when you run it on the server, the things above probably only apply if it fails too. If not, dunno, sorry.
  • Options
    aynalunaaynaluna Member Posts: 5
    The XML is definitly smaller than 4 MB (is a small tiny file of 2KB ;-P )

    Fortunally all the samples i had display definitly work just fine on Classic Client, unfortunally this all comes crashing into pieces as soon as testing with the RCT.

    So it must be something in the way RCT (with the NAS web service and NAS service) is running, been different of the classic client, and is what makes the difference.

    any way that succesfully sends messages to a qeueu from navision using MSMQ components (using RCT) could do....

    any ideas?
  • Options
    fredefrede Member Posts: 80
    I think you should move code concerning communication with MSMQ and other related "stuff" to be executed by NAS or other schedulers.

    Then you do not delay or disturb the user - and you only need to have correct OCX, Automations and so on on the NAS server.

    I've found this is very much easier to support and test.

    You need to build a "communications log" or other that holds the jobs to be executed - but actually it is quite easy and makes the system very smooth to test for heavy traffic, response time and other..

    Best regards and happy coding!
    Regards,

    Henrik Frederiksen, Denmark
  • Options
    aynalunaaynaluna Member Posts: 5
    Hello everyone.
    Thank you very much for your opinions and helps. They were all taked in consideration and very helpful.
    After lots or research and trying to use MSMQ in many different ways (inlcuding with the NAS) we have decided to use instead a directory with xml files.
    It looks like a few solutions are viable and work on the classic, but not in the RCT.
    But again, thank you all for you help.
    Cheers
    Ayna
  • Options
    rdebathrdebath Member Posts: 383
    OOps, forgot, I was going to try this on the RTC first. Nevermind, I've only tried this on Classic but as it only uses pretty basic automation techniques it should work fine. Though you may need to replace the ScriptControl OCX with the DLL alternative. That is 'Microsoft Script Control 1.0'.ScriptControl
    OBJECT Codeunit 90027 MSMQPost No DLL
    {
      OBJECT-PROPERTIES
      {
        Date=04/11/09;
        Time=22:12:19;
        Modified=Yes;
        Version List=;
      }
      PROPERTIES
      {
        OnRun=VAR
                I@1000000000 : Integer;
                starttime@1000000001 : DateTime;
              BEGIN
                MSMQInit('Direct=OS:.\Private$\dump');
    
                starttime := CURRENTDATETIME;
                FOR I := 1 TO 1000 DO
                  Test;
                MESSAGE('RunTime = %1', CURRENTDATETIME - starttime);
              END;
    
      }
      CODE
      {
        VAR
          TestNo@1000000001 : Integer;
          MSMQInfo@1000000003 : Automation "{D7D6E071-DCCD-11D0-AA4B-0060970DEBAE} 3.0:{D7D6E07C-DCCD-11D0-AA4B-0060970DEBAE}:'Microsoft Message Queue 3.0 Object Library'.MSMQQueueInfo";
          MSMQueue@1000000002 : Automation "{D7D6E071-DCCD-11D0-AA4B-0060970DEBAE} 3.0:{D7D6E079-DCCD-11D0-AA4B-0060970DEBAE}:'Microsoft Message Queue 3.0 Object Library'.MSMQQueue";
          RUNPostMSMQ@1000000000 : OCX "{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}:'ScriptControl Object'";
    
        PROCEDURE MSMQInit@1000000001(FormatName@1000000000 : Text[80]);
        BEGIN
          CREATE(MSMQInfo);
          MSMQInfo.FormatName := FormatName;
          MSMQueue := MSMQInfo.Open(2, 0); // MQ_SEND_ACCESS, MQ_DENY_NONE
        END;
    
        PROCEDURE MSMQPost@1000000003(VAR XML@1000000000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v3.0'.DOMDocument";MessageID@1000000001 : Text[30]);
        VAR
          MSMQMsg@1000000002 : Automation "{D7D6E071-DCCD-11D0-AA4B-0060970DEBAE} 3.0:{D7D6E075-DCCD-11D0-AA4B-0060970DEBAE}:'Microsoft Message Queue 3.0 Object Library'.MSMQMessage";
        BEGIN
          CREATE(MSMQMsg);
    
          RUNPostMSMQ.Language('VBScript');
          RUNPostMSMQ.Reset;
          RUNPostMSMQ.AddObject('XMLin', XML);
          RUNPostMSMQ.AddObject('MSMQMsg', MSMQMsg);
    
          MSMQMsg.Label := MessageID;
          MSMQMsg.Delivery := 1; // MQMSG_DELIVERY_RECOVERABLE -- Reliable
          MSMQMsg.Priority := 2; // A little below normal
          MSMQMsg.Journal := 1; // MQMSG_DEADLETTER -- Don't lose them
          RUNPostMSMQ.ExecuteStatement('MSMqMsg.body = XMLin.xml');
          MSMQMsg.Send(MSMQueue);
        END;
    
        PROCEDURE Test@1000000005();
        VAR
          XML1@1000000000 : Automation "{F5078F18-C551-11D3-89B9-0000F81FE221} 3.0:{F6D90F11-9C73-11D3-B32E-00C04F990BB4}:'Microsoft XML, v3.0'.DOMDocument";
        BEGIN
          CREATE(XML1);
          TestNo += 1;
          XML1.loadXML('<XML>œ TEST' + FORMAT(TestNo) + '</XML>');
          MSMQPost(XML1, 'Test1');
        END;
    
        BEGIN
        END.
      }
    }
    
    
  • Options
    dgwdgw Member Posts: 3
    Hello All

    Has anyone had success in sending xml messages from the RTC to msmq?
    Using the same objects, I can send a message to msmq when in the classic client. I have paused the queue and confirmed this works. A messages goes in.
    When you try to run this in the RTC, I encounter the message that someone posted above:
    "The call to member send failed. There is insufficient memory to perform the operation on the stream"

    I have debugged this and all passes through seemingly well until I call the .Send() function for automation variable Navision Communication Component Version 2.OutMessage. This is in a codeunit which I obviously call also in the classic client without problems.

    I have downloaded a hotfix and this didnt work. Also tried disabling the journals on the message queues, no luck. Changed the service account to admin, restarted no luck.

    Can this be achieved in the RTC or is this a case of re-writing with webservices?
    Thanks alot
    Dave
  • Options
    rdebathrdebath Member Posts: 383
    I did test my bit of code above on the RTC afterwards, it seems that the OCX will only run on the client side so you do have to substitute it with the Automation. Once you've done that it happily dumps messages into the queue. (Server side)

    So it looks like the MS Bus DLLs are bust.
  • Options
    dgwdgw Member Posts: 3
    Thanks for the reply Robert.

    I am using 'Navision Communication Component version 2'.OutMessage which is already an automation type variable - we encounter the error when we call the send function.

    The other automation variables we use are 'Navision MS-Message Queue Bus Adapter'.MSMQBusAdapter and also the 'Microsoft XML, v3.0'.DOMDocument

    As you found, a tricky one this to decide whether to try to keep going to get it to work in rtc, especially as it all works in classic or to try another approach.
  • Options
    ngebhardngebhard Member Posts: 127
    Hello everybody,

    I am glad that I found this thread, because I have a similar problem. I already get this to work when I create the file on the server, but I get an error message while creating it on a client. I suggest that there is a problem adressing the queue. Could you give me an example how you adressed it? This would be really helpful!

    Thanks in advance!
    Greetz
    Nicole
    ProTAKT Projekte & Business Software AG
    Microsoft Dynamics NAV Partner
    Bad Nauheim, Germany
    http://www.protakt.de
    http://twitter.com/protakt
  • Options
    TFCrowtherTFCrowther Member Posts: 35
    Hi

    Built the Message Queue stuff in CLASSIC and blam, all fails in RTC. grrr

    Using code from RASHEDhttp://mibuso.com/blogs/ara3n/2011/04/02/integrating-with-msms-using-dotnet-data-types-in-nav-2009-r2/

      Name DataType Subtype Length xmlDom DotNet 'System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Xml.XmlDocument Q DotNet 'System.Messaging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Messaging.MessageQueue QActiveXFormatter DotNet 'System.Messaging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Messaging.ActiveXMessageFormatter TempGUID GUID RTCTempFileName Text 250

    SendItem(p_item : Record Item)
    //SEND TO SCRIBE VM - INTEGRATION
    Q := Q.MessageQueue('FormatName:Direct=OS:INTEGRATION\PRIVATE$\ScribeIn');  //(use .\PRIVATE$\ for localhost)
    
    TempGUID := CREATEGUID;
    RTCTempFileName := TEMPORARYPATH + '\' + COPYSTR(FORMAT(TempGUID),2,STRLEN(FORMAT(TempGUID))-2) +'.xml';  //3tier file management
    
    TextFile.CREATE(RTCTempFileName);
    
    
    TextFile.CREATEOUTSTREAM(OutStr);
    ProductXMLPort.SetVariables(p_item."No.",p_item.Description,p_item."Base Unit of Measure",
                                p_item."Unit Price",p_item.Blocked,p_item."Gen. Prod. Posting Group",0);
    ProductXMLPort.SETDESTINATION(OutStr);
    ProductXMLPort.EXPORT;
    
    TextFile.CLOSE;
    
    xmlDom := xmlDom.XmlDocument;
    xmlDom.Load(RTCTempFileName);
    
    Q.Formatter :=  QActiveXFormatter.ActiveXMessageFormatter;
    
    Q.Send(xmlDom.InnerXml, 'NAV Label');
    CLEAR(xmlDom);
    


    Successfully sent a XML to the Message Queue on another VM via RTC.

    <?xml version="1.0" standalone="no" ?>
    - <Products ScribeObject="Product" ScribeOperation="Update" ScribeLabel="Product" Label="NAVProductToCRM" MessageLabel="NAVProductToCRM">
    - <Product>
    <No.>A05</No.>
    <Description>ARIZONA 5</Description>
    <Base_Unit_of_Measure>EA</Base_Unit_of_Measure>
    <Unit_Price>0</Unit_Price>
    <Blocked>No</Blocked>
    <Gen_Prod_Posting_Group>SYSTEMS</Gen_Prod_Posting_Group>
    <Type>0</Type>
    </Product>
    </Products>

    Hope this helps
Sign In or Register to comment.