| By Stanimir Stanev, Rob Bartlett | Article Rating: |
|
| March 3, 2008 06:00 AM EST | Reads: |
14,236 |
.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,236
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
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- Confessions of a Ulitzer Addict
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- It's the Java vs. C++ Shootout Revisited!
- Cloud Computing Can Revitalize Your Career as Software Developer
- IBM Could "Reinvent" Java: Mills
- Oracle & Cloud Computing: Exclusive Q&A with SVP Richard Sarwal
- A Brief History of Cloud Computing
- Kindle 2 vs Nook
- Cloud CEOs, CTOs & SVPs to Speak at 4th International Cloud Computing Expo
- Why IBM’s Server Chief Got Busted
- Is Cloud Computing Like Teenage Sex?
- Industry Experts Discuss the State of Cloud Computing
- Performance Tuning Essentials for Java
- The Difference Between Web Hosting and Cloud Computing
- Cloud Computing Expo: Exclusive Q&A with Yahoo! SVP Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- My Thoughts on Ulitzer
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- The i-Technology Right Stuff
- JavaServer Faces (JSF) vs Struts
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- What's New in Eclipse?
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- i-Technology Predictions for 2007: Where's It All Headed?








































