4 Programming Considerations
This chapter includes the following sections:
- Using WebLogic JMS Extensions
- Limitations of Using the WebLogic JMS .NET Client
- Exchanging Messages Between Different Language Environments
- Specifying the URL Format
- Implementing Security With the JMS .NET Client
- Configuring Logging and Debugging
- Understanding Socket and Threading Behavior
- Data Conversion Between Java and .NET
- Best Practices
Using WebLogic JMS Extensions
Table 4-1 lists the WebLogic JMS extensions that are supported in this release of the JMS .NET client. There are several ways that messaging can be configured:
-
On the connection factory—This method often defines default configuration settings.
-
Programmatically in the application using the API—Certain programming constructs may override the connection factory configuration.
-
On the server—Certain settings may override both the connection factory and programmatic constructs.
In some cases, there are differences in the way that an extension is configured, or in the behavior, between a JMS .NET client and a Java client. For example, some extensions cannot be enabled programmatically using the JMS .NET API, and can only be enabled via configuration. The following table summarizes the differences. Additional details, if required, are provided in the subsequent sections.
Table 4-1 WebLogic JMS Extensions Supported in the JMS .NET Client
Feature | Configurable on Connection Factory | Configurable on the Server | Java API | JMS .NETAPI | Comments |
---|---|---|---|---|---|
Distributed Destinations (Uniform and Weighted) For more information, see:
|
Yes |
Yes |
No |
No |
|
Flow Control Producers For more information, see: Controlling the Flow of Messages on JMS Servers and Destinations in Tuning Performance of Oracle WebLogic Server |
Yes |
Yes |
No |
No |
|
Blocking producers during quota conditions For more information, see Defining a Send Timeout on Connection Factories in Tuning Performance of Oracle WebLogic Server |
Yes |
Yes |
No |
No |
|
Foreign destinations for remote instances of WebLogic Server For more information, see Configuring Foreign Server Resources to Access Third-Party JMS Providers in Administering JMS Resources for Oracle WebLogic Server |
No |
Yes |
No |
No |
|
Imported store-and-forward (SAF) destinations For more information, see Imported SAF Destinations in Administering the Store-and-Forward Service for Oracle WebLogic Server |
No |
Yes |
No |
No |
|
Redelivery limit For more information, see Setting a Redelivery Limit for Messages in Developing JMS Applications for Oracle WebLogic Server |
No |
Yes |
Yes |
No |
|
Redelivery delay For more information, see Setting a Redelivery Delay for Messages in Developing JMS Applications for Oracle WebLogic Server |
Yes |
No |
Yes |
No |
|
Error destinations For more information, see Configuring an Error Destination for Undelivered Messages in Developing JMS Applications for Oracle WebLogic Server |
No |
Yes |
No |
No |
|
No |
No |
Yes |
Yes |
||
No Acknowledge Mode For more information, see Using NO_ACKNOWLEDGE in Developing JMS Applications for Oracle WebLogic Server |
No |
No |
Yes |
Yes |
|
Unit-of-Order For more information, see:
|
Yes |
Yes |
Yes |
Yes |
See Unit-of-Order. |
Scheduled message delivery For more information, see Setting Message Delivery Times in Developing JMS Applications for Oracle WebLogic Server |
Yes |
Yes |
Yes |
Yes |
|
Asynchronous consumer messages maximum pipeline
|
Yes |
No |
Yes |
No |
|
Message Compression For more information, see Message Compression in Developing JMS Applications for Oracle WebLogic Server |
Yes |
No |
Yes |
No |
See Message Compression. |
Quotas For more information, see Defining Quota in Tuning Performance of Oracle WebLogic Server |
No |
Yes |
No |
No |
|
One-way message sends For more information, see Using One-Way Message Sends in Tuning Performance of Oracle WebLogic Server |
Yes |
No |
No |
No |
|
Acknowledge policy |
Yes |
No |
No |
No |
|
Automatically include user-id as message property |
Yes |
Yes |
No |
No |
|
Get number of delivery attempts as message property |
No |
No |
No |
No |
- Message Compression
- Unit-of-Order
- Message Delivery Time
- One-Way Message Sends
- Include user-id as JMSXUserId
- Message Delivery Attempts
Parent topic: Programming Considerations
Message Compression
In this release, automatic message compression is not supported for client sends between the JMS .NET client and the JMS .NET client host running on WebLogic Server. However, if the compression settings are set on the connection factory, message compression behavior between the .NET client host and the destination is the same as that of the Java client. The behavior is as follows:
-
If the client host and destination run on different instances of WebLogic Server, then a sent message is automatically compressed on the client host.
-
If the client host and destination run on the same instance of WebLogic Server, then no sent message compression will occur.
Compressed messages are decompressed by the JMS .NET client host on the server side when they are received by the .NET client.
For more information, see Message Compression in Developing JMS Applications for Oracle WebLogic Server
Parent topic: Using WebLogic JMS Extensions
Unit-of-Order
The method used to specify Unit-of-Order (UOO) in the JMS .NET API differs from the
Java API. To set Unit-of-Order in the JMS .NET API, add a string property named
Constants.MessagePropertyNames.UNIT_OF_ORDER_PROPERTY_NAME
to the
message with the desired UOO.
For more information, see Using Message Unit-of-Order in Developing JMS Applications for Oracle WebLogic Server
Parent topic: Using WebLogic JMS Extensions
Message Delivery Time
The method used to specify message delivery times in the JMS .NET API differs from
the Java API. To set message delivery times in the JMS .NET API, add a property of type
long
named
Constants.MessagePropertyNames.DELIVERY_TIME_PROPERTY_NAME
to the
message, where the value is the number of milliseconds in the future in which the
message will be delivered.
Parent topic: Using WebLogic JMS Extensions
One-Way Message Sends
Although you can configure one-way message sends on the connection factory, this behavior is not fully supported in the JMS .NET client. Messages sent as one-way sends will actually be two-way sends between the .NET client and the .NET client host, and one-way sends between the .NET client host and the JMS connection host.
Parent topic: Using WebLogic JMS Extensions
Include user-id as JMSXUserId
The optional JMSXUserId
system-generated message property on received messages specifies the credential of the original sender. To enable this property, configure the Attach Sender Credential attribute on destinations, distributed destinations, or templates, and configure the Attach JMSXUserId attribute on connection factories. To retrieve, call msg.GetStringProperty(Constants.MessagePropertyNames.USER_ID_PROPERTY_NAME)
.
Parent topic: Using WebLogic JMS Extensions
Message Delivery Attempts
The JMSXDeliveryCount
system-generated message property on received messages specifies the number of message delivery attempts. The first attempt is 1. To retrieve the value, call msg.GetIntProperty(Constants.MessagePropertyNames.DELIVERY_COUNT_PROPERTY_NAME
.
Parent topic: Using WebLogic JMS Extensions
Limitations of Using the WebLogic JMS .NET Client
The following sections describe the JMS features that are not supported in the JMS .NET client.
- Unsupported JMS 2.0 Standard Features
- Unsupported JMS 1.1 Standard Features
- Unsupported JMS 1.1 Optional Features
- Unsupported WebLogic JMS Extensions
- Transactions
Parent topic: Programming Considerations
Unsupported JMS 2.0 Standard Features
In this release, the JMS 2.0 standard feature 'shared topic subscriptions' is not supported. The workaround is to use the shared subscription feature in Oracle JMS by configuring a custom connection factory and setting the Subscription Sharing Policy attribute on the connection factory as Sharable
and Client ID Policy as Unrestricted
.
For more information, see Shared Subscriptions and Client ID Policy in Developing JMS Applications for Oracle WebLogic Server.
Parent topic: Limitations of Using the WebLogic JMS .NET Client
Unsupported JMS 1.1 Standard Features
In this release, the following JMS 1.1 standard features are not supported:
-
Creating and closing temporary destinations (
javax.jms.TemporaryQueue
andjavax.jms.TemporaryTopic
). The JMS .NET client can still produce messages to temporary destinations created by a Java client if the destination objects are obtained from the JMSReplyTo header of received messages. -
javax.jms.QueueRequester
andjavax.jms.TopicRequester
. (These helper classes are related to temporary destinations.) -
Queue browsers:
javax.jms.QueueBrowser
. -
Queue and Topic interfaces (
QueueConnectionFactory
,TopicConnectionFactory
,QueueConnection
,TopicConnection
,QueueSession
,TopicSession
). These queue and topic interfaces are legacy JMS 1.0.2 interfaces that have been superseded by the JMS 1.1 common interfaces.
Parent topic: Limitations of Using the WebLogic JMS .NET Client
Unsupported JMS 1.1 Optional Features
In this release, the following JMS 1.1 optional features are not supported:
-
XA interfaces (
XAConnectionFactory
,XAConnection
, andXASession
). -
Participation in global XA transactions (See Transactions).
-
Connection Consumer and Server session pools (
javax.jms.ConnectionConsumer
,ServerSessionPool
, andServerSession
). These are optional capabilities that have been superseded by Java EE MDBs, and are not supported by the WebLogic Java JMS client. -
MessageProducer.setDisableMessageTimestamp
method. Note that the WebLogic JMS client ignores this method.
Parent topic: Limitations of Using the WebLogic JMS .NET Client
Unsupported WebLogic JMS Extensions
In this release, the following WebLogic JMS extensions are not supported:
-
SSL
-
HTTP tunneling
-
SAF Client—See Reliably Sending Messages Using the JMS SAF Client in Developing Standalone Clients for Oracle WebLogic Server
-
Multicast Subscribers—See Using Multicasting with WebLogic JMS in Developing JMS Applications for Oracle WebLogic Server
-
Automatic Reconnect—See Automatic JMS Client Failoverin Developing JMS Applications for Oracle WebLogic Server
-
Unit-of-Work—If a .NET client attempts to set a UOW property on a message, a
Weblogic.Messaging.MessageException
is generated. In addition, a .NET consumer cannot receive UOW messages with deserializable content that are sent by a Jakarta client. In this case, the consumer gets aMessageFormatException
if it calls theObjectMessage.getObject()
method on theObjectMessage
. Note that while Unit-of-Work is not supported, the more commonly used Unit-of-Order extension is fully supported. For more information about Unit-of-Order, see Unit-of-Order.Note:
The JMS .NET API does not provide extensions for programmatically configuring JMS resources (for example, topics and queues). In Java, programmatic configuration is accomplished using JMX MBeans or the
weblogic.jms.extensions.JMSModuleHelper
helper class. Alternative ways to configure JMS include WLST scripting and the WebLogic Remote Console.
Parent topic: Limitations of Using the WebLogic JMS .NET Client
Transactions
In this release, the JMS .NET client supports transacted sessions as defined in the JMS Specification only. Transacted sessions provide a standard local transaction capability. As with the Jakarta client, one or more WebLogic JMS destinations from within the same cluster may participate in a transacted session local transaction, but no other resources may participate (such as JMS servers in other clusters, databases, or foreign JMS providers).
Global XA transactions are not supported, therefore JMS cannot participate in a .NET transaction. The XA setting of the connection factory is ignored by the .NET client. The JMS NET client operations cannot participant in any .NET transactions.
Parent topic: Limitations of Using the WebLogic JMS .NET Client
Exchanging Messages Between Different Language Environments
The following Java JMS message types can be exchanged between a .NET producer and a Java or C consumer, and vice versa:
-
Message
-
BytesMessage
-
StreamMessage
-
MapMessage
-
TextMessage
An ObjectMessage
type, however, can be sent from one language and received by another, but the message cannot be interpreted unless it is written in the same language. The producer and consumer of an OBJECTMESSAGE
type must be written in the same language, either C# or Java. If a mismatch occurs; that is, if a .NET ObjectMessage
is received by a Java consumer, or a Java ObjectMessage
is received by a .NET consumer, then message.getObject()
throws a MessageFormatException
.
Parent topic: Programming Considerations
Specifying the URL Format
The Provider_URL
may contain multiple addresses, separated by commas, using the following format:
t3://address [,address]...
where a particular address may specify multiple port ranges.
The syntax for specifying multiple addresses is as follows:
address = hostlist : portlist
where
hostlist = hostname [, hostname]...
portlist = portrange [+ portrange]...
portrange = port [- port]
Use port -port
to indicate a port range, and +
(plus sign) to separate multiple port ranges.
Table 4-2 provides sample URL formats.
Table 4-2 URL Format Examples
This format . . . | Can also be specified as . . . |
---|---|
|
|
|
|
|
|
Parent topic: Programming Considerations
Using DNS Alias Host Names
You can also specify DNS alias host names, which are expanded into multiple hosts. For example, if a DNS alias mycluster
resolves to host1,host2
, then the URL t3://mycluster:7001
expands into the address list: t3://host1:7001,host2:7001
. Contexts that are created with the URL will always retry with host2
if host1
is unreachable. DNS aliases are typically configured by network administrators.
Parent topic: Specifying the URL Format
Implementing Security With the JMS .NET Client
You need to be aware of the following security considerations when creating a JMS .NET client:
-
To access secure JNDI and JMS resources on the server, the JMS .NET client application can supply a user name and password as follows:
-
When establishing the initial context to the server using
ContextFactory.CreateContext()
. The credentials supplied when creating the initial context are used for authentication to gain access to secure JNDI and JMS resources on the server. -
When creating a connection using the
IConnectionFactory.createConnection()
method. In this case, the credentials supplied when creating a connection override the credentials supplied during the initial context. That is, if userFred
is supplied during initial context, and userTony
is supplied when the connection is created, the userTony
credential is used for authentication to gain access to secure JMS resources.Note:
- In both instances, the password is encrypted.
- If the resources are not secured, a user name and
password is optional. But if your application encounters an
exception with the error message The Microsoft .NET
client is required to provide credential info, you
need to either provide a user name and password (see Example 4-1), or enable anonymous access using
-Dweblogic.security.remoteAnonymousRMIT3Enabled=true
on the server startup command. See Disable Remote Anonymous RMI T3 and IIOP Requests in Securing a Production Environment for Oracle WebLogic Server. - Although user names and passwords are protected, and passwords are encrypted, a sophisticated user or intruder might be able to defeat the protection mechanisms. Be sure to secure any network connections when user names and passwords are provided.
-
-
Authentication for the .NET client is associated with the JMS object that invokes the secured resource. That is, the credential for a JMS object is inherited from the parent JMS context, or from the connection override if credentials are supplied when creating the connection. This differs from Java client security where credentials are associated with the current thread.
-
SSL is not supported for the JMS .NET client in this release. Therefore, it is important that you secure the networking services that the operating system provides, as well as any networking connections. For more information, see Secure the Network in Securing a Production Environment for Oracle WebLogic Server.
-
Similar to the Java client, the JMS.NET client does not support message level encryption.
-
Due to the use of non-encrypted communication, sniffing of application traffic (see
http://www.owasp.org/index.php/Sniffing_application_traffic_attack
) is possible. You need to either accept these risks, or take remediation such as using a firewall to protect against these attacks. -
The administration port, if configured, accepts only SSL traffic, and all connections via the port require administrator privileges. In addition, once an administration port is configured, all other ports will refuse connections that have administrator privileges. Because SSL is not supported for the JMS .NET client in this release, it cannot support users with administrative privileges if an administration port is configured.
Example 4-1 Create a Context With a User Name and a Password
IDictionary<string, Object> paramMap = new Dictionary<string, Object>();
paramMap[Constants.Context.PROVIDER_URL] = "t3://host:port";
paramMap[Constants.Context.SECURITY_PRINCIPAL] = "fred";
paramMap[Constants.Context.SECURITY_CREDENTIALS] = "fredpassword";
IContext context = ContextFactory.CreateContext(paramMap);
Parent topic: Programming Considerations
Configuring Logging and Debugging
Basic logging and debugging is available for the server-side transport and .NET client host running on WebLogic Server.
Parent topic: Programming Considerations
Server Side
To enable debugging on the server side, use the following commands:
-Dweblogic.debug.DebugJMSDotNetT3Server=true -Dweblogic.debug.Debug.JMSDotNetProxy=true
Parent topic: Configuring Logging and Debugging
Client Side
Client-side logging and debugging are enabled and controlled by various configuration settings in two categories:
Message Output
You should specify whether log messages are output to the console or saved to a file as shown in Table 4-3.
Table 4-3 Message Output Settings
Key | Value | Setting |
---|---|---|
|
String |
Indicates the full path and file name for the log file. For example
Note: The default log file size limit is 500KB. Each time the log file
reaches this size, the server renames the log file and creates a new
|
|
Boolean |
|
Parent topic: Client Side
Log Categories and Levels
Client-side logging is grouped into the following categories:
-
Socket
-
T3
-
Transport
-
PhysicalMsg
-
LogicalMsg
-
All
(represents all individual categories listed above)
Off(0)
Error(1)
Warning(2)
Info(3)
Verbose(4)
Note:
The severity level on theAll
category overrides the setting
on each individual category.
When using Version 1 libraries with a .Net Framework application
The client side logging and debugging are configured and controlled using an
application configuration file. For generated build files, the application
configuration file is named yourapplicationname.exe.config
,
while yourapplicationname
is the name of the application that
runs the messaging client.
Example 4-2 provides the XML content that needs to be added to your application configuration file to
configure logging and debugging. The subsequent sections provide additional details about
each of the different settings. If you have an existing
yourapplicationname.exe.config
file, add the XML content shown in the
following listing to the file. Otherwise, you can create one and locate it in the same
directory that contains the yourapplicationname.exe
file.
Note:
If you are using Visual Studio, the logging and debugging settings shown in Example 4-2 need to be added to theApp.config
file. For instructions to add an
App.config
file to your C# project inside a Visual Studio
environment, see the Microsoft website.
Example 4-2 XML File Content for yourapplicationname.exe.config
File
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- To forward log output to a file, please uncomment the following line, and replace the file name with the desired one -->
<!--- <add key="weblogic.debug.JMSDotNet.config.LogFileName" value="c:\test\MyLogFile.log" /> -->
<!-- To prevent log messages from displaying to the console, use the value 'false' -->
<!-- <add key="weblogic.debug.JMSDotNet.config.IsLogToConsole" value="false" /> -->
</appSettings>
<system.diagnostics>
<switches>
<!-- Please set the switch value as desired for logging to each Category -->
<!-- value for Off=0, Error=1, Warning=2, Info=3, Verbose=4 -->
<!-- if "AllLogger" is enabled (no zero for the value), every individual category is set to the same level as the AllLogger,
no matter how individual category's value is set -->
<add name="weblogic.debug.JMSDotNet.All" value="0" />
<add name="weblogic.debug.JMSDotNet.Socket" value="0" />
<add name="weblogic.debug.JMSDotNet.T3" value="0" />
<add name="weblogic.debug.JMSDotNet.Transport" value="0" />
<add name="weblogic.debug.JMSDotNet.PhysicalMsg" value="0" />
<add name="weblogic.debug.JMSDotNet.LogicalMsg" value="0" />
</switches>
</system.diagnostics>
</configuration>
Note:
In a .Net Core environment, the XML application config file settings are not honored anymore; instead, consider using the latest version of the libraries with theappsettings.json
file. See Example 4-3.
When using Version 2 libraries with a .Net Core application
The client side logging and debugging is configured and controlled in the
application's appsettings.json
file in a .Net Core (2.1 and
later) environment.
Example 4-3 JSON File Content for the appsettings.json
File
{
"weblogic.debug.JMSDotNet.ALL": {
"Level": "0"
},
"weblogic.debug.JMSDotNet.Socket": {
"Level": "0"
},
"weblogic.debug.JMSDotNet.T3": {
"Level": "0"
},
"weblogic.debug.JMSDotNet.Transport": {
"Level": "0"
},
"weblogic.debug.JMSDotNet.PhysicalMsg": {
"Level": "0"
},
"weblogic.debug.JMSDotNet.LogicalMsg": {
"Level": "0"
},
"weblogic.debug.JMSDotNet.config.LogFileName": "c:\\test\\MyLogFile.log",
"weblogic.debug.JMSDotNet.config.IsLogToConsole": "false"
}
Parent topic: Client Side
Understanding Socket and Threading Behavior
WebLogic JMS .NET clients share the same WebLogic Server T3 port as other types of WebLogic clients. When an IContext
initial context is created by a .NET client using the ContextFactory
class, the client specifies a URL that references a T3 capable port on the server, and a socket pair is implicitly created to service the requested network connection. The socket pair consists of one socket on the client and another socket on the WebLogic Server JMS .NET client host. All JMS operations on JMS objects obtained from the .NET context route through the implicit network connection of the context.
If two concurrent IContext
initial context instances on the same
.NET environment connect to the same WebLogic Server JMS .NET client host, then two
network connections are created. Each network connection has its own pair of sockets: a
server-side socket and a client-side socket. Therefore, when two network connections are
created, two sockets are created on the CLR client and two sockets are created on the
WebLogic Server acting as the JMS .NET client host. This contrasts with WebLogic Java
clients, which automatically detect and close duplicate network connections to a remote
JVM and, instead, implicitly multiplex all traffic to and from a particular remote JVM
over a single network connection.
A server-side socket for a JMS .NET client is serviced by the same WebLogic Server socket-reader muxer thread pool as other types of WebLogic clients. When working on behalf of JMS .NET client requests, the socket-reader muxer thread pool reads the incoming requests from the socket and dispatches work into the WebLogic Server default thread pool which, in turn, processes the requests and sends the responses back to the client.
On a JMS .NET client, a new internal thread is automatically created for each network connection (that is, per IContext
initial context instance). This dedicated thread reads all incoming data on the client socket and dispatches the related work into the CLR thread pool. This means that asynchronous message event handlers in the .NET client application run in the CLR thread pool.
Note:
The CLR thread pool is supplied by the .NET Framework System.Threading.ThreadPool class. There is one thread pool per process. The thread pool has a default size of 25 threads per available processor, however, you can change the number of threads in the thread pool using the ThreadPool.SetMaxThreads method. Each thread in the thread pool uses the default stack size and runs at the default priority. For more information, refer to the Microsoft .NET Framework documentation for the System.Threading.ThreadPool class.
For JMS .NET applications that create many concurrent initial contexts that all connect to the same WebLogic Server .NET client host, you may obtain performance improvements by modifying the application so that it uses a single, shared initial context. A shared context ensures that the client only creates a single network connection.
Parent topic: Programming Considerations
Data Conversion Between Java and .NET
See the following sections:
Parent topic: Programming Considerations
Endian Conversions
Java and .NET use different byte order formats for storing primitive types:
-
Microsoft Windows .NET uses the Little-Endian (low-order) format
-
Java uses the Big-Endian (high-order) format
To support interoperability between Java and .NET, data is transferred over the network using the Big-Endian format. When a .NET application uses the JMS .NET API to read and write primitives, data is automatically converted between Big-Endian and Little-Endian, as needed. For example, if you use BytesMessage.WriteInt
in the JMS .NET API, the data is always stored as Big Endian and can be read using both the Java API and the JMS .NET API bytes message read integer methods.
For specialized applications that do not use the JMS .NET API to pass primitives, but instead transfer primitive data using raw byte arrays, you need to manually convert the byte format to Big Endian when communicating with Java. If you need to perform a manual Endian conversion in your application, you can use the following helper methods from the utility class WebLogic.Messaging.Transport.Util.EndianConvertor
provided in the JMS .NET client library:
public static char SwitchEndian(char x) public static short SwitchEndian(short x) public static int SwitchEndian(int x) public static long SwitchEndian(long x) public static ushort SwitchEndian(ushort x) public static uint SwitchEndian(uint x) public static ulong SwitchEndian(ulong x) public static double SwitchEndian(double x) public static float SwitchEndian(float x) public static byte[] SwitchEndian(byte[] x)
For example, the standard .NET classes System.IO.BinaryReader
and System.IO.BinaryWriter
for reading and writing primitives to raw byte arrays use Little Endian. The following code snippet illustrates how to store and retrieve an integer to/from a .NET byte array:
binaryWriter.WriteInt(EndianConverter.SwitchEndian(i)) i=EndianConverter.SwitchEndian(binaryReader.ReadInt())
Parent topic: Data Conversion Between Java and .NET
Signed and Unsigned Byte Conversions
With the exception of the byte
data type, there is an equivalent C# data type, with the same name and definition, for every Java primitive data type. The following table lists the different names used for signed and unsigned bytes in C# and Java.
Table 4-4 Byte Primitive Data Type in C# and Java
C# | Java | Description |
---|---|---|
|
|
Unsigned byte |
|
|
Signed byte |
As shown in Table 4-4, Microsoft .NET supports both byte
(unsigned byte) and sbyte
(signed byte) as primitive data types, but Java supports only byte
(signed byte) as a direct primitive type. The standard convention in both languages is to use the byte
data type; however, in .NET this represents an unsigned byte and in Java this represents a signed byte.
For interoperability between .NET and Java, the JMS .NET client allows only the use of the signed byte for reading and writing bytes. There is no difference between signed bytes and unsigned bytes when the byte value is 127 or less. An unsigned byte with a value of 127 or less is stored as an sbyte
. However, if a .NET client needs to store an unsigned byte with a value greater than 127 in a signed byte, it needs to be converted from a signed byte to an unsigned byte. The following samples illustrate conversion methods that you can use to read and write an unsigned byte as a signed byte:
-
Byte Conversion in C#
An unsigned byte value of 255 can be passed as a signed byte as follows:
-
byte unsignedByteValue = 255;
-
sbyte signedByteValue = unchecked ( (sbyte)unsignedByteValue ); // converted signed value=-1
Similarly, you can use the following method to convert a signed byte value to an unsigned byte value:
-
sbyte signedByteValue = -1;
-
byte unsignedByteValue = unchecked ( (byte)signedByteValue ); // converted unsigned value=255
-
-
Byte Conversion in Java
The unsigned value can be read as a signed byte and converted to an unsigned byte value as follows:
-
byte signedByteValue = -1;
-
int unsignedByteValue = 0xFF & signedByteValue; //converted signed value = 255
An unsigned value can be written as follows:
-
Int unsignedByteValue = 255;
-
byte signedByteValue = 0xFF & unsignedByteValue; // converted signed value=-1
-
The JMS .NET API only allows for storing single bytes as signed bytes. When the JMS .NET API is used to retrieve sbyte
values as short
, int
, long
, or string
, the value is treated as an sbyte
, not an unsigned byte. For example, if the unsigned byte value 255 is stored using message.SetByteProperty("myvalue", unchecked( (sbyte)((byte)255) ))
, a call to message.GetByteProperty("myvalue")
or message.GetShortProperty("myvalue")
returns "-1".
Parent topic: Data Conversion Between Java and .NET
Byte Array Transfers
When transferring byte arrays from the JMS .NET client to WebLogic JMS, all byte arrays (byte[])
are passed as is (that is, there is no conversion from unsigned to signed.) Therefore, no data is lost in the translation.
Parent topic: Data Conversion Between Java and .NET
Time Conversions
The WebLogic JMS .NET API represents dates and times using Java rather than .NET conventions. The JMSTimestamp and JMSExpiration attributes of the WebLogic.Messaging.IMessage
message interface are type long
and contain a millisecond absolute time value as specified in the Java programming language. The Java millisecond absolute time value is the difference, measured in milliseconds, between a given time and midnight, January 1, 1970 UTC.
The following examples demonstrate how to convert between .NET times and Java millisecond absolute time values.
Example 4-4 Example C# Code for Converting the Current .NET Time to Java Millisecond Time
// Example: C# code for converting the current .NET time to Java millisecond time DateTime baseTime = new DateTime(1970, 1, 1, 0, 0, 0); DateTime utcNow = DateTime.UtcNow; long timeInMillis = (utcNow.Ticks - baseTime.Ticks)/10000; Console.WriteLine(timeInMillis);
Example 4-5 Example C# Code for Converting Java Millisecond Time to .NET Time
// Example: C# code for converting Java millisecond time to .NET time DateTime baseTime = new DateTime(1970, 1, 1, 0, 0, 0); long utcTimeTicks = (timeInMillis * 10000) + baseTime.Ticks; DateTime utcTime = new DateTime(utcTimeTicks, DateTimeKind.Utc); Console.WriteLine(utcTime); Console.WriteLine(utcTime.ToLocalTime());
Parent topic: Data Conversion Between Java and .NET
Best Practices
The following list identifies best practices to use when creating a JMS .NET client application:
-
Always register a connection exception listener using an
IConnection
if the application needs to take action when an idle connection fails. The connection exception listener is asynchronously notified when there is a communications failure between the .NET client and the .NET client WebLogic host, or between the WebLogic host and the JMS connection host. Applications may choose to implement the connection exceptions listener callback to close all open resources and then periodically attempt a reconnect. -
To obtain performance improvements, have multiple .NET client threads share a single context to ensure that they use a single socket. See Understanding Socket and Threading Behavior. It is important to note that a context creates a socket and that closing the context closes the socket.
-
Cache and reuse frequently accessed JMS resources, such as contexts, connections, sessions, producers, destinations, and connection factories. Creating and closing these resources consumes significant CPU and network bandwidth.
-
With the exception of
close()
methods, JMS sessions and their child resources are not thread safe. For example, do not call a producersend()
in one thread, and a consumerreceive()
in parallel in another thread, if the producer and consumer were created using the same session. As another example, do not call any method other thanclose()
in an arbitrary thread for sessions that have asynchronous consumers because a message may arrive and invoke the callback at the same time. -
Use DNS aliases or comma separated addresses for load balancing JMS .NET clients across multiple JMS .NET client host servers in a cluster. In this release, the JMS .NET client does not support automatic cluster load balancing as is implicitly supplied with the Java client.
Parent topic: Programming Considerations