| By Stanimir Stanev, Rob Bartlett | Article Rating: |
|
| March 3, 2008 06:00 AM EST | Reads: |
14,220 |
.NET SOAP over JMS
Boiled down, this JMS solution
hijacks the SOAP request before it goes over the wire, sends it over
JMS, listens for a response via JMS then returns the SOAP response back
to the caller, allowing it to finish processing. We only pass the SOAP
through the system - we don't have to do anything special to generate
it, process it, serialize it, or deserialize it. We let .NET do the
heavy lifting that it was going to do anyway.
Normally, a Web Service will use an HTTP URI. When the Web Service proxy makes http calls, it causes the WebRequest.Create() method to produce an instance of HttpWebRequest. The proxy generates the SOAP, hands it off to the HttpWebRequest, which sends it over the wire, gets a response, and then sends that to the HttpWebResponse. Finally, the proxy takes over again.
We're going to take advantage of the "pluggable protocol" feature in .NET to make using JMS almost transparent. We say "almost" because we don't want to supersede HTTP in all cases - just for certain services. First, we'll need to know what flavor of JMS we're using. For this article, we're focusing on ActiveMQ because it's freely available and already has a pure .NET API. The .NET API we use is from Spring.NET. There are other options, such as OpenMQ and Tibco. Even if there were no .NET APIs already, we could wrap a dll. If the API existed only in Java, there are technologies such as JNBridge that can bridge technologies.
Once the JMS API is selected, we need to create several components: an ActiveMqWebResponse, an ActiveMqWebRequest, an ActiveMqWebRequestCreate, and an ActiveMqSoapStream - a specialized stream for hijacking the SOAP. These classes are custom versions of the components used in the normal flow of HTTP Web Services. Then, of course, we need a consumer.
ActiveMqSoapStream
The specialized stream is where
we do the fancy footwork to hijack the SOAP. We don't want the proxy to
realize it's dealing with a special stream. This class inherits
System.IO.Stream and is mostly a pass-through to an encapsulated
stream. The primary difference is that it overrides the Close() method
called by the base WebRequest. Instead of closing the stream, this
method rewinds the inner stream so our hijacking code can process the
stream from the beginning. It also has an internal close method that
our ActiveMqWebRequest will call to truly close the underlying stream
when it's done with it, otherwise the stream would stay open
indefinitely.
public class ActiveMqSoapStream : Stream
{
private Stream m_Stream;
public override void Close()
{ m_Stream.Position = 0;}
internal void InternalClose()
{ if (this.CanSeek == true) m_Stream.Close();}
}
ActiveMqWebRequest
The ActiveMqWebRequest is where
the bulk of the work happens. It inherits from System.NET.WebRequest
and implements the abstract methods and properties. There are a few
custom properties for JMS-specific information such as the address,
username, password, and queue name. We also have a field of type
ActiveMqSoapStream.
public class ActiveMqQueueWebRequest : WebRequest
{
protected ActiveMqSoapStream m_RequestStream;
private string _password;
private string _username;
private string _queueAddress;
private string _queueName;
...
For brevity's sake, I won't go into the details of the property accessors or pass-through methods. The methods we're most interested in are GetRequestStream() and GetResponse(). GetRequestStream() is where we replace the default stream with our own.
public override Stream GetRequestStream()
{
m_RequestStream = new ActiveMqSoapStream(new MemoryStream(), true, true, true);
return m_RequestStream;
}
GetResponse() is where we send the request, listen for a response, and then put the response in a return stream. This is the workhorse of the class. The first thing we do is access the SOAP stream as an array of bytes.
public override WebResponse GetResponse()
{
byte[] bytBody = new Byte[m_RequestStream.Length];
m_RequestStream.Read(bytBody, 0, bytBody.Length);
Next we create the connections we're going to be using. We create a temporary queue as a response destination. This lets us have a request/response model instead of an asynchronous model. If we wanted an asynchronous model, we could listen to a permanent queue and then use the correlation ID to match the response to our request.
ConnectionFactory connectionFactory = new ConnectionFactory(_queueAddress);
try
{ using (IConnection connection = connectionFactory.CreateConnection())
{ using (ISession session = connection.CreateSession())
{
//Create a temporary queue so we can listen for the response
ITemporaryQueue queue = session.CreateTemporaryQueue();
using (IMessageConsumer consumer = session.CreateConsumer(queue))
{
Published March 3, 2008 Reads 14,220
Copyright © 2008 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Stanimir Stanev
Stanimir Stanev is a senior consultant at MomentumSI's Enterprise Architecture Solutions practice. He has many years of experience focusing on providing enterprise architecture and strategy expertise to companies looking to migrate to or maximize the advantages of SOA principles.
More Stories By Rob Bartlett
Rob Bartlett is a senior consultant at MomentumSI's Software Development Solutions practice. He has over a decade of experience in technical roles, guiding major corporations in the design, implementation, and integration of business solutions.
- Kindle 2 vs Nook
- Confessions of a Ulitzer Addict
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Infrastructure-as-a-Service Will Mature in 2010: Microsoft's David Chou
- Windows 7 – Microsoft’s First Step to the Cloud
- Cloud Expo and the End of Tech Recession
- Jill Tummler Singer, Deputy CIO of CIA, Keynotes at GovIT Expo
- Reality Check at the Cloud Computing Expo
- Visual Studio 2010 Is Cloud Friendly
- Fired SCO CEO Fires Back
- Kindle 2 vs Nook
- The Difference Between Web Hosting and Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- Wave on Ulitzer: Confessions of a Google Wave Fanboy
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- Cloud Computing Best Practices
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Infrastructure-as-a-Service Will Mature in 2010: Microsoft's David Chou
- Eval JavaScript in a Global Context
- Windows 7 – Microsoft’s First Step to the Cloud
- Google Maps and ASP.NET
- Crystal Reports XI & How It Has Changed
- Converting VB6 to VB.NET, Part I
- Creating Controls for.NET Compact Framework in Visual Studio 2005
- Where Are RIA Technologies Headed in 2008?
- How to Write High-Performance C# Code
- AJAX World RIA Conference & Expo Kicks Off in New York City
- Implementing Tab Navigation with ASP.NET 2.0
- i-Technology Photo Exclusive: Bill Gates & Steve Jobs In "Nerds"
- .NET Archives: Getting Reacquainted with the Father of C#
- i-Technology Viewpoint: "SOA Sucks"
- Programmatically Posting Data to ASP .NET Web Applications




























