是否可以为传出的MQMessage更改PutApplicationType?

时间:2012-07-09 14:09:19

标签: java .net ibm-mq

我有类似MQ消息的消息转发器/路由器。我正在尝试根据一些规则转发消息。这种转发只需通过从一个队列接收消息,创建新消息(具有相同或修改的内容)并将其放入另一个队列来完成。货运代理的存在应该尽可能透明。

目前我的问题是PutApplicationType消息属性。看起来我无法改变这个属性。我有.NET和Java示例实现,我只想使用:

MQMessage forwardedMessage = new MQMessage();
forwardedMessage.putApplicationType = CMQC.MQAT_UNIX;

我尝试使用的值无关紧要。 .NET版本始终发送带有MQAT_DEFAULT / MQAT_WINDOWS_NT的消息,Java版本始终发送带有MQAT_JAVA的消息。

是否可以更改此标题?如果不是,如果我不更改值,它是否会对遗留系统造成一些问题?为什么无法更改值?

顺便说一下。转发原始邮件也不起作用 - 我的应用程序也将更改PutApplicationType属性。

编辑:如果我使用原生C API,我将能够控制此属性的内容吗?

4 个答案:

答案 0 :(得分:3)

正如T.Rob所说,你需要阅读manaul(WMQ使用Java或WMQ使用.Net)。转发邮件并不是您上面列出的简单任务。有几个选项/参数需要正确设置。

这是一个包含所有异常处理的Java代码段:

int openInputOptions  = MQC.MQOO_INQUIRE + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_INPUT_SHARED + MQC.MQOO_SAVE_ALL_CONTEXT;
int openOutputOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING + MQC.MQOO_PASS_ALL_CONTEXT;

MQQueue _inQ = _qMgr.accessQueue( inQueueName, openInputOptions, null, null, null );

MQQueue _outQ = _qMgr.accessQueue( outputQueueName, openOutputOptions, null, null, null );

MQGetMessageOptions getOptions = new MQGetMessageOptions();
getOptions.options = MQC.MQGMO_NO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING;

MQMessage mqMsg = new MQMessage();

mqMsg.correlationId = MQC.MQCI_NONE;
mqMsg.messageId = MQC.MQMI_NONE;

_inQ.get(mqMsg, getOptions);

MQPutMessageOptions pmo = new MQPutMessageOptions();
pmo.options =  MQC.MQPMO_FAIL_IF_QUIESCING + MQC.MQPMO_PASS_ALL_CONTEXT;
pmo.contextReference = _inQ;

_outQ.put(mqMsg, pmo);

答案 1 :(得分:1)

有两种方法可以做到这一点,具体取决于您希望的安全程度。第一种更安全的方法是从原始消息传递上下文。此方法保留上下文,而不允许程序更改任何内容。这是通过在队列打开时使用MQOO_SAVE_ALL_CONTEXT来获取消息和在队列中使用MQOO_PASS_ALL_CONTEXT来放置消息来实现的。

另一种选择是直接设置上下文。这不太安全,因为应用程序可以将字段设置为任意值。如果使用该消息的应用程序依赖于授权的上下文,则允许上游应用程序绕过该授权。有几个选项,具体取决于应用程序需要访问哪组上下文信息。

请参阅知识中心的Controlling message context information

所有这些都绝对适用于C实现。我不知道它在.Net实现中暴露了多少。也许Shashi会在单独的回复中填写这些细节。

答案 2 :(得分:1)

是的,MQ .NET还支持所有这些与上下文相关的属性。

这是我的.NET应用程序版本,它使用原始发送应用程序设置的相同应用程序类型转发消息。

使用MQOO_SET_ALL_CONTEXT,因为我将消息放在同一个应用程序中

            MQQueue recvQ = qm.AccessQueue("Q1", MQC.MQOO_INPUT_SHARED | MQC.MQOO_OUTPUT | MQC.MQOO_SET_ALL_CONTEXT | MQC.MQOO_SAVE_ALL_CONTEXT | MQC.MQOO_FAIL_IF_QUIESCING);
            MQQueue fwdQ = qm.AccessQueue("Q2", MQC.MQOO_OUTPUT | MQC.MQOO_PASS_ALL_CONTEXT | MQC.MQOO_FAIL_IF_QUIESCING);

            MQMessage putMsg = new MQMessage();
            putMsg.WriteString("Verify PutApplicationType");
            putMsg.Persistence = MQC.MQPER_NOT_PERSISTENT;

            putMsg.PutApplicationType = MQC.MQAT_UNIX;
            putMsg.PutApplicationName = "UnixApplication";
            putMsg.Format = MQC.MQFMT_STRING;

            MQPutMessageOptions pmo = new MQPutMessageOptions();
            pmo.Options = MQC.MQPMO_SET_ALL_CONTEXT;
            recvQ.Put(putMsg,pmo);

            MQGetMessageOptions gmo = new MQGetMessageOptions();
            gmo.WaitInterval = MQC.MQWI_UNLIMITED;
            gmo.Options = MQC.MQGMO_WAIT;
            MQMessage fwdMsg = new MQMessage();
            recvQ.Get(fwdMsg, gmo);

            MQPutMessageOptions pmoF = new MQPutMessageOptions();
            pmoF.Options = MQC.MQPMO_FAIL_IF_QUIESCING + MQC.MQPMO_PASS_ALL_CONTEXT;
            pmoF.ContextReference = recvQ;
            fwdQ.Put(fwdMsg, pmoF);

            recvQ.Close();
            fwdQ.Close();

答案 3 :(得分:1)

  

这适用于转发,但它引发了许多与并行处理相关的新问题 - 是否可以从同一个MQQueue实例并行处理多个消息?

当然,我编写的应用程序一直都是并行运行的。确保每个线程都有自己的与队列管理器的连接。

  

我猜它只能保留最后收到的消息的上下文。

真。 (对于那个特定的主题)

  

如果我可以简单地设置PutApplicationType字段,它也没有回答我的主要问题 - 它可能与创建@T.Rob提到的新上下文有关。

您应该参加MQ课程,因为您没有阅读T.Rob给您的手册页。如果您阅读这些页面(和子章节),那么您将了解到MQMD有7个字段,您不能简单地设置它们并由队列管理器控制。

队列管理器控件:

  1. 身份背景:

    • 用户ID
    • AccountingToken
    • 的applicationID
  2. Origin Context:

    • PutApplType
    • PutApplName
    • PutDate
    • PutTime
  3. 您可以“设置”或“传递”身份上下文,也可以“设置全部”或“全部通过”原始上下文。如果要更改MQMD的PutApplType字段(它是Origin Context的一部分),那么必须使用'Set All'上下文,并且您必须设置MQMD的所有7个Context字段,因为队列管理器不会设置它们。

    所以让我绝对清楚,如果你使用'Set All'选项,那么应用程序没有明确设置的上面列出的7个字段中的任何一个都将为null(包括PutDate / PutTime)。